第十节 Shiro集成SSM框架

网友投稿 614 2022-11-16

第十节 Shiro集成SSM框架

第十节 Shiro集成SSM框架

一、搭建基本的SSM框架

首先告诉大家一个好消息,现在github的私有仓库免费咯。

基本的SSM框架导入到你的开发工具里后,你需需要稍作修改,将jdbc.properties里面配置的数据库信息,改为你的本机的MySQL数据库的帐号密码。

基本的SSM框架启动系统后的基本页面如图所示。

数据库t_user表的数据如图所示

二、开始集成Shiro

(1)第一步,我们需要配置web.xml,首先在web.xml中定义一个shiroFilter。在web.xml中加入如下代码。         在下述配置中,从这个filter-class的名字就能够知道,DelegatingFilterProxy这个类是一个代理类。代理谁呢?它会代理Spring容器中bean的id为"shiroFilter"的类。         PS:Shiro的依赖我已经编写在了基本的SSM框架中。

shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true shiroFilter /actions/*

(2)第二步,编写shiro.xml配置文件,编译器会帮你找到你需要编写的自定义类。

/actions/security/login = anon /actions/admin/** = authc,permissionFilter,roles[coder] /actions/logout = logout /actions/** = authc

在applicationContext.xml中导入刚才编写的 shiro.xml

(3)编写自定义Realm与-。相信你已经发现了,你的编译器已经报警,说找不到com.jay.shiro.UserRealm与userAccessControlFilter这两个类,不要着急,放轻松,这两个类让我们慢慢的开始编写。        首先编写的是UserRealm,这个是自定义Realm。如何自定义Realm,在前置章节中已经详细的讨论过,也追踪过其源码,如果你有点生疏,可以查看前面的一些文章哦。在本小节大宇不做过多阐述如何自定义Realm。

package com.jay.shiro;/** * @author jay.zhou * @date 2019/1/10 * @time 14:23 */import com.jay.service.UserService;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;import java.util.Arrays;import java.util.List;/** * @author jay.zhou * @date 2019/1/10 * @time 10:57 */public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; /** * 强制重写的认证方法 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //还记得吗,token封装了客户端的帐号密码,由Subject拉客并最终带到此处 String clientUsername = (String) token.getPrincipal(); //从数据库中查询帐号密码 String passwordFromDB = userService.findPasswordByName(clientUsername); if (passwordFromDB == null) { //如果根据用户输入的用户名,去数据库中没有查询到相关的密码 throw new UnknownAccountException(); } /** * 返回一个从数据库中查出来的的凭证。用户名为clientUsername,密码为passwordFromDB 。封装成当前返回值 * 接下来shiro框架做的事情就很简单了。 * 它会拿你的输入的token与当前返回的这个数据库凭证SimpleAuthenticationInfo对比一下 * 看看是不是一样,如果用户的帐号密码与数据库中查出来的数据一样,那么本次登录成功 * 否则就是你密码输入错误 */ return new SimpleAuthenticationInfo(clientUsername, passwordFromDB, "UserRealm"); } //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String yourInputUsername = (String) principals.getPrimaryPrincipal(); //构造一个授权凭证 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //通过你的用户名查询数据库,得到你的权限信息与角色信息。并存放到权限凭证中 info.addRole(getYourRoleByUsernameFromDB(yourInputUsername)); info.addStringPermissions(getYourPermissionByUsernameFromDB(yourInputUsername)); //返回你的权限信息 return info; } private String getYourRoleByUsernameFromDB(String username) { return "coder"; } private List getYourPermissionByUsernameFromDB(String username) { return Arrays.asList("code:insert", "code:update"); }}

(4)第四步,编写剩下的一个自定义类:用户自定义-。此类可用于判断用户是否已经拥有相关的角色或者权限。

package com.jay.shiro;import org.apache.shiro.SecurityUtils;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.AccessControlFilter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.* @author jay.zhou * @date 2019/1/10 * @time 14:34 */@Component("userAccessControlFilter")public final class UserAccessControlFilter extends AccessControlFilter { private static final Logger LOGGER = LoggerFactory.getLogger(UserAccessControlFilter.class); /** * 即是否允许访问,返回true表示允许. * 如果返回false,则进入本类的onAccessDenied方法中进行处理 */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object object) throws Exception { final Subject subject = SecurityUtils.getSubject(); //判断用户是否进行过登录认证,如果没经过认证则返回登录页 if (subject.getPrincipal() == null || !subject.isAuthenticated()) { return Boolean.FALSE; } final String requestURI = this.getPathWithinApplication(request); if (LOGGER.isDebugEnabled()) { LOGGER.debug("请求URL为:{}", requestURI); } final String requestHeader = ((HttpServletRequest) request).getHeader("Referer"); //防盗链处理 if (requestHeader == null || "".equals(requestHeader)) { return Boolean.FALSE; } //此处可以编写用于判断用户是否有相关权限的代码 //subject.hasRole("需要的角色"); //subject.isPermitted("需要的权限"); return Boolean.TRUE; } /** * 如果返回true,则继续执行其它- * 如果返回false,则表示拦截住本次请求,且在代码中规定处理方法为重定向到登录页面 */ @Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { if (LOGGER.isDebugEnabled()) { LOGGER.debug("当前帐号没有相应的权限!"); } //重定向到登录页面 this.redirectToLogin(servletRequest, servletResponse); return Boolean.FALSE; }}

编写完自定义Realm与自定义Shiro-,再次查看shiro.xml配置文件,发现编译器已经不报红。(5)第五步,编写jsP来验证SSM框架是否成功集成Shiro。        编写login.jsp页面。

<%@ taglib prefix="c" uri="%><%@ page contentType="text/html;charset=UTF-8" language="java" %> Title

" method="post"> 用户名
密码

login.jsp发送的表单请求需要编写Java代码来处理。处理/actions/security/login请求的Controller代码如下。

@RequestMapping(value = "security/login", method = {RequestMethod.POST}) public String login(@RequestParam("username") String userName, @RequestParam("password") String password) { //获取到Subject门面对象 Subject subject = getSubject(); try { //将用户数据交给Shiro框架去做 //你可以在自定义Realm中的认证方法doGetAuthenticationInfo()处打个断点 subject.login(new UsernamePasswordToken(userName, password)); } catch (AuthenticationException exception) { if (!subject.isAuthenticated()) { //登录失败 return "fail"; } } //登录成功 return "home";

接下来编写登录成功的 home.jsp 与登录失败的fail.jsp         在web-inf/pages/目录下,编写home.jsp页面。编写一个进入管理员页面的超链接,再编写一个退出登录的超链接。

<%@ taglib prefix="c" uri="%><%@ page contentType="text/html;charset=UTF-8" language="java" %> 主页您已经登录成功
">回到首页
">进入管理员页面
">退出,此请求会被shiro的退出-捕获

在web-inf/pages/目录下,编写登录失败的fail.jsp页面

<%@ taglib prefix="c" uri="%><%@ page contentType="text/html;charset=UTF-8" language="java" %> 登录失败 ">重新登录

(6)第六步, 在web-inf/pages/目录下编写管理员页面 admin.jsp,并在Controller中编写处理代码。

<%@ taglib prefix="c" uri="%><%@ page contentType="text/html;charset=UTF-8" language="java" %> Title管理员页面
">回到首页

@RequestMapping(value = "admin") public String enterAdmin() { //跳转到 web-inf/pages/admin.jsp页面 return "admin"; }

最后,把index.jsp页面修改一下

<%@ taglib prefix="c" uri="%><%@ page contentType="text/html;charset=UTF-8" language="java" %> hello world

下面的第一个超链接测试是否返回JSON数据

">测试超链接
">进入管理员页面
">退出

至此,整个搭建环节就已经完毕了。

三、代码分析

启动集成Shiro后的框架,让我们回到最初的页面。

首先,我们在浏览器上输入​​this.redirectToLogin(servletRequest, servletResponse);

我们接着往下走,刚才isAccessAllowed方法返回的是true,说明此次请求已经成功放行。不过在图中,我们知道,还有最后一个限制:是否含有coder权限。shiro对权限的校验会拿到自定义Realm中的doGetAuthorizationInfo方法中去对比。

OK,我们最后再在UserRealm的doGetAuthorizationInfo方法处打个断点。如果你已经成功到达admin.jsp页面,可以退出后重新操作一波,或者直接重启项目。打了断点后,请求会来到我们的doGetAuthorizationInfo方法处。从图中可以清楚的看到,本次请求执行了自定义Realm的授权操作。Shiro会问你,这个登录的人它有什么权限呀?我们可以从数据库中查询当前登录人的权限信息与角色信息。当然了,我这里偷了个懒,getYourRoleByUsernameFromDB方法直接返回了一个"coder",表明从数据中查询出来的角色信息是coder。

然后Shiro就会进行判断,Shiro发现本次需要的请求角色信息是coder,这个人的角色信息包含了coder,所以验证通过。最终此请求成功来到了admin.jsp页面。

关于上面退出后应该跳转哪个页面的问题,你可以新增像这样配置,规定退出后跳转 /index.jsp页面。

好了,本期SSM框架集成Shiro就结束了。如果你有问题,欢迎留言哦。

四、源码-

----------------------------------------------------分割线-------------------------------------------------------

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:第四节 Shiro权限管理
下一篇:jQuery全屏滚动插件fullPage.js
相关文章

 发表评论

暂时没有评论,来抢沙发吧~