shiro学习:shiro整合springweb项目实现用户登录和退出
来源:互联网 发布:单片机开发板 编辑:程序博客网 时间:2024/04/29 16:17
在上一篇:shiro整合SpringMVC中,我们已经将shiro和springmvc进行了整合,所以我们在其基础上进行修改。
一、实现原理
使用FormAuthenticationFilter过虑器实现 ,原理如下:
将用户没有认证时,请求loginurl进行认证,用户身份和用户密码提交数据到loginurl
FormAuthenticationFilter拦截住取出request中的username和password(两个参数名称是可以配置的)
FormAuthenticationFilter调用realm传入一个token(username和password)
realm认证时根据username查询用户信息(在Activeuser中存储,包括 userid、usercode、username、menus)。
如果查询不到,realm返回null,FormAuthenticationFilter向request域中填充一个参数(记录了异常信息)
二、自定realm
2.1修改doGetAuthenticationInfo方法
首先我们从token获取用户输入的username,根据用户输入的username去数据库中查找用户的信息,如果查不到用户信息直接返回null,然后进入loginController,因为没有查询到用户信息,就会跳转到登录页面;如果能到查到用户的信息,那么我们就获取用户的密码和盐(shiro的散列算法),最后我们会实例化出一个activeUser对象用来存储用户的菜单和权限信息,然后返回认证信息。
public class CustomRealm extends AuthorizingRealm {@Resourceprivate SysService sysService;@Overridepublic void setName(String name) {// TODO Auto-generated method stubsuper.setName("customRealm");}//用于授权//Authorization 授权的意思@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//从 principals获取主身份信息//将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal();// 根据身份信息获取权限信息// 从数据库获取到权限数据List<SysPermission> permissionList = null;try {permissionList = sysService.findPermissionListByUserId(activeUser.getUserid());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}// 单独定一个集合对象List<String> permissions = new ArrayList<String>();if (permissionList != null) {for (SysPermission sysPermission : permissionList) {// 将数据库中的权限标签 符放入集合permissions.add(sysPermission.getPercode());}}// 查到权限数据,返回授权信息(要包括 上边的permissions)SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();// 将上边查询到授权信息填充到simpleAuthorizationInfo对象中simpleAuthorizationInfo.addStringPermissions(permissions);return simpleAuthorizationInfo;}//用户认证//Authentication 认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.第一步从token中取出用户名String userCode = (String) token.getPrincipal();//2.根据用户名查询用户SysUser sysUser = null;try {sysUser = sysService.findSysUserByUserCode(userCode);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}//如果查询不到返回nullif(sysUser == null){return null;}//获得密码String password = sysUser.getPassword();//盐String salt = sysUser.getSalt();// 实例化对象ActiveUser activeUser = new ActiveUser();activeUser.setUserid(sysUser.getId());activeUser.setUsercode(sysUser.getUsercode());activeUser.setUsername(sysUser.getUsername());// 通过server取菜单List<SysPermission> menus = null;try {menus = sysService.findMenuListByUserId(sysUser.getId());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}activeUser.setMenus(menus);// 如果找到了返回认证信息AuthenticationSimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(activeUser, password,ByteSource.Util.bytes(salt),this.getName());return simpleAuthenticationInfo;}}2.2ActiveUser实体类
public class ActiveUser implements java.io.Serializable {private String userid;//用户id(主键)private String usercode;// 用户账号private String username;// 用户名称private List<SysPermission> menus;// 菜单private List<SysPermission> permissions;// 权限2.3修改shiro的配置文件
配置shiro的散列,并将器注入得到realm中(完整的配置文件参考下边)
<!-- 自定义 realm --><bean id="customRealm" class="org.lpl.controller.shiro.CustomRealm"><property name="credentialsMatcher" ref="credentialsMatcher" /></bean><!-- 凭证匹配器 必须放到realm的下边--><bean id="credentialsMatcher"class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><!-- 采用MD5进行加密 --><property name="hashAlgorithmName" value="md5" /><!-- 设置散列次数 --><property name="hashIterations" value="1" /></bean>
三、修改登录的jsp页面
FormAuthenticationFilter进行拦截的时候,默认情况下他从request中拿到的登录信息是,username和password这两个,如下图
FormAuthenticationFilter拦截住取出request中的username和password,所以我们需要保证jsp页面中请求的参数也要是这样
3.1当然我们也可以修改登录的默认属性(配置文件参考下边)
3.1.1.修改shiro的配置文件(在我们设置的凭证器下边加入)
<!-- 自定义的form验证器 --><!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --><bean id="formAuthenticationFilter" class="org.lpl.controller.shiro.MyFormAuthenticationFilter "><!-- 表单中账号的input名称 --><property name="usernameParam" value="usercode" /><!-- 表单中密码的input名称 --> <property name="passwordParam" value="password" /><!-- 配置自动登录 --><property name="rememberMeParam" value="rememberMe" /> </bean>在shiroFilter中加入
<property name="securityManager" ref="securityManager" /><!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 --><property name="loginUrl" value="/login.do" /><!-- 认证成功同意跳转到first.action 建议不要配置,shiro自动到上一个请求路径 --><property name="successUrl" value="/index.do" /><!-- 通过unauthorizedUrl指定没有权限操作时的权限页面 --><property name="unauthorizedUrl" value="/refuse.jsp" /><!-- 自定义filter --><property name="filters"><map><!-- FormAuthenticationFilter是基于表单认证的过虑器 --><entry key="authc" value-ref="formAuthenticationFilter" /></map></property>3.1.2创建一个MyFormAuthenticationFilter
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {return super.onAccessDenied(request, response);}}
四、看一下现在shiro的配置文件(本篇讲到的所有配置文件)
我们在shiro的过滤连中配置了/logout.action = logout,就可以实现了退出功能
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "><!-- web.xml中shiro的filter需要的bean --><!-- Shiro 的Web过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 --><property name="loginUrl" value="/login.do" /><!-- 认证成功同意跳转到first.action 建议不要配置,shiro自动到上一个请求路径 --><property name="successUrl" value="/index.do" /><!-- 通过unauthorizedUrl指定没有权限操作时的权限页面 --><property name="unauthorizedUrl" value="/refuse.jsp" /><!-- 自定义filter --><property name="filters"><map><!-- FormAuthenticationFilter是基于表单认证的过虑器 --><entry key="authc" value-ref="formAuthenticationFilter" /></map></property><!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 --><property name="filterChainDefinitions"><value><!-- 对静态资源设置匿名访问 -->/images/** = anon/js/** = anon/styles/** = anon<!-- 验证码 --><!-- /validatecode.jsp = anon --><!-- 请求logout.action shiro去清除session 147895-->/logout.action = logout<!-- 商品查询页面,注释掉该方法,在controller中进行注解配置 --><!-- /items/queryItems.action = perms[item:query]/items/editItems.action = perms[item:edit] --><!-- 配置记住我或认证通过可以访问的地址 --><!-- /index.jsp = user/first.action = user/welcome.jsp = user --><!--/** = authc 所有的url都授权后才能访问 -->/** = authc<!-- /** 所有的url都可以匿名访问--></value></property></bean><!-- SecurityManager --><!-- 安全管理器 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><!-- 注入自定义realm --><property name="realm" ref="customRealm" /></bean><!-- 自定义 realm --><bean id="customRealm" class="org.lpl.controller.shiro.CustomRealm"><property name="credentialsMatcher" ref="credentialsMatcher" /></bean><!-- 凭证匹配器 必须放到realm的下边--><bean id="credentialsMatcher"class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><!-- 采用MD5进行加密 --><property name="hashAlgorithmName" value="md5" /><!-- 设置散列次数 --><property name="hashIterations" value="1" /></bean><!-- 自定义的form验证器 --><!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --><bean id="formAuthenticationFilter" class="org.lpl.controller.shiro.MyFormAuthenticationFilter "><!-- 表单中账号的input名称 --><property name="usernameParam" value="usercode" /><!-- 表单中密码的input名称 --> <property name="passwordParam" value="password" /><!-- 配置自动登录 --><property name="rememberMeParam" value="rememberMe" /> </bean> </beans>
五、修改登录的Controller
因为已经将登录的验证交给了FormAuthenticationFilter,如果登录信息没问题他会直接跳转到我们配置的登录成功页面(如果不进行配置,他会直接跳到上一个请求页面),如果登录过程中出现错误,他会获取错误信息然后进行返回
LoginController用于显示登录表单页面,其中shiro authc拦截器进行登录,登录失败的话会把错误存到shiroLoginFailure属性中,在该控制器中获取后来显示相应的错误信息
/** * 此方法只处理登录失败,如果登录成功shiro会自动跳转到上一个请求路径 * @param request * @return * @throws Exception */@RequestMapping("login.do")//这个路径要和shiro.xml配置的路径要一样public String login(HttpServletRequest request) throws Exception{//如果登录不成功String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");//根据shiro返回的异常类路径判断,抛出异常if(exceptionClassName!=null){if(UnknownAccountException.class.getName().equals(exceptionClassName)){throw new CustomException("账号不存在");}else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){throw new CustomException("用户名或密码错误");}else if("randomCodeError".equals(exceptionClassName)){throw new CustomException("验证码错误");}else{throw new Exception();}}//登录失败跳进这个页面return "login";}4.2登录成功跳转到首页
@Controllerpublic class MainController {/** * 跳转到首页 * @param model * @return */@RequestMapping("index.do")public String goIndex(Model model){//从shiro的session中获取ActiveUserSubject subject = SecurityUtils.getSubject();//获取身份信息ActiveUser activeUser = (ActiveUser) subject.getPrincipal();//通过model传到页面中model.addAttribute("activeUser", activeUser);return "/first";}}六、退出
<!-- 请求logout.action shiro去清除session 147895-->/logout.action = logout
- shiro学习:shiro整合springweb项目实现用户登录和退出
- Shiro实现用户登录
- shiro整合开发-实现登陆和退出功能
- Shiro实现用户自动登录
- Shiro 整合SpringMVC 并且实现权限管理,登录和注销
- Shiro 整合SpringMVC 并且实现权限管理,登录和注销
- Shiro整合Spring实现登录验证和授权之入门
- Shiro 整合SpringMVC 并且实现权限管理,登录和注销
- SpringBoot+shiro整合学习之登录认证和权限控制
- SpringBoot+shiro整合学习之登录认证和权限控制
- 使用shiro进行登录和退出
- spring boot整合Shiro实现单点登录
- 【shiro】shiro和sping整合
- shiro基础学习(四) shiro与项目整合
- shiro基础学习(四)—shiro与项目整合
- shiro学习:shiro整合SpringMVC的web项目
- Shiro整合SSH开发2:结合Struts2实现登陆和退出以及Shiro执行流程和原理解析
- 4、Shiro+Oracle实现用户登录认证
- AM2开发日志3 10.22
- make/makefile二
- Android统计图表MPAndroidChart
- 2017-10-21 集训总结
- conda list File "J:\Anaconda\Scripts\conda-script.py", line 8 reload(sys)
- shiro学习:shiro整合springweb项目实现用户登录和退出
- 段式、页式内存管理--学习《Linux内核源代码情景分析》第一章
- 学习阶段总结(4)2017.10.15-10.22
- 第八周项目对矩阵的压缩存储1
- ireport报表打印(3)
- Nginx之基础入门
- python读取配置文件
- Mysql Order By 注入总结
- mmu访问权限