06-Spring集成Shiro(ssm+Shiro)
这一章能解决的问题:(目录)
需求1:spring整合shiro
需求2:集成shiro的认证操作
需求3:
3.1.登录成功后,在页头显示“欢迎XXX”
3.2.把该用户的菜单显示出来
需求4:把自定义Realm中的用户信息改成动态的,并使用md5散列
需求5:授权---从数据库授权
需求6:使用注解的方式和shiro标签的方式配置
需求7:使用注解方式进行授权
需求8:shiro的缓存(针对上面授权的频繁查询数据库的问题,这里要使用shiro缓存来解决)
需求9:管理员一旦修改了用户的某个权限,要立即生效,即使用户不退出系统和不关闭浏览器,也要立即生效!
需求10:会话的实现
需求11:验证码的实现
需求12:记住我的实现
-------------------------------------------------------------------------
流程:
在项目的基础上演示:(项目的搭建这里就不演示,直接在一个项目上演示,注:传智播客的项目)
===========================================================================
需求1:spring整合shiro
web中实现权限访问控制是通过认证拦截器和授权拦截器来实现的,而shiro中也是使用shiro的拦截器来实现的,而且shiro中是使用很多拦截器:
比如:认证拦截器、授权拦截器、sessionManager、ehcacheManager等等
加入jar包:
shiro-spring-1.2.3.jar、shiro-web-1.2.3.jar、commons-beanutils-1.8.3.jar、commons-logging-1.1.1.jar、
junit-4.9.jar、log4j-1.2.17.jar、shiro-core-1.2.3.jar、slf4j-api-1.7.5.jar、slf4j-log4j12-1.7.5.jar
一、在web.xml中配置shiro的Filter
<!-- Shiro的Filter:DelegatingFilterProx会从spring容器中找shiroFilter --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
二、自定义Realm,CustomRealm.java(还需要修改)
package cn.itcast.ssm.realm; import java.util.ArrayList; import java.util.List; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; // 自定义Realm public class CustomRealm extends AuthorizingRealm { /** * 认证 token:用户输入的令牌,可以是字符串,也可以是对象 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 从token中获取用户名 String username = (String) token.getPrincipal(); // 根据用户输入的用户名从数据库中查找用户信息(密码),这里只是模拟的静态数据 // 如果查不到就返回null... // 假设数据库中的用户名是PeterDB if (!"zhang".equals(username)) { return null; // 返回null之后,下面的代码都不执行 } // 如果查到就返回password String password = "123"; // 返回认证信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( username, password, this.getName()); return simpleAuthenticationInfo; } // Realm的名称(自定义),可以不定义 @Override public void setName(String name) { super.setName("customRealm"); } /** * 授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 授权是在认证通过后的操作,principals是认证通过后返回的SimpleAuthenticationInfo对象的第一个参数 String username = (String) principals.getPrimaryPrincipal(); // 模拟数据库的静态数据(开发中要从数据库中获取) List<String> permissions = new ArrayList<String>(); permissions.add("user:create"); // 添加用户 permissions.add("items:add"); // 添加商品 // 返回权限信息 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.addStringPermissions(permissions); return simpleAuthorizationInfo; } }
三、创建applicationContext-shiro.xml(还需要修改)
securityManager:这个属性是必须的。
loginUrl:没有登录认证的用户请求将跳转到此地址,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。
unauthorizedUrl:没有权限默认跳转的页面。
<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 "> <!-- Shiro 的Web过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 如果没有认证将要跳转的登陆地址,http可访问的url,如果不在表单认证过虑器FormAuthenticationFilter中指定此地址就为身份认证地址 --> <property name="loginUrl" value="/login.action" /> <!-- 认证成功后的跳转路径,但建议不配置,因为shiro如果认证成功会自动跳转到上一个请求路径 --> <!-- <property name="successUrl" value="/first.action"/> --> <!-- 没有权限跳转的地址 --> <property name="unauthorizedUrl" value="/refuse.jsp" /> <property name="filterChainDefinitions"> <value> <!-- /** = anon 所有的URL都可以匿名访问 --> /**=anon </value> </property> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> </bean> <!-- 自定义 realm --> <bean id="userRealm" class="cn.itcast.ssm.realm.CustomRealm"></bean> </beans>
运行测试:
因为以上去掉了拦截器,并且使用了shiro的拦截器,因为所有请求都配置成了/**=anon,即所有URL都匿名访问,所以这时候直接输入:
http://localhost:8080/ssm_shiro/first.action回车就会进入到主页面,并不用登录:
需求2:集成shiro的认证操作
认证通过的用户使用自定义po类接收:ActiveUser.java(getter/setter省略)
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;// 权限
LoginController.java:
@Controller public class LoginController { @RequestMapping("/login") public String login(HttpServletRequest request) throws Exception { // 如果登录失败,从request中获取认证失败的信息,shiroLoginFailure String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); // 异常信息处理 if (exceptionClassName != null) { if (UnknownAccountException.class.getName().equals(exceptionClassName)) { throw new CustomException("账号不存在"); } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) { throw new CustomException("密码错误"); } else { throw new Exception(); // 未知错误 } } // 认证成功,shiro会自动跳转到上一个请求路径 // 认证失败会跳转到登录 return "login"; } }
修改applicationContext-shiro.xml:
<!-- 请求logou.action地址,shiro去清除session --> /logout.action=logout <!-- 处理静态资源被拦截 --> /images/**=anon /js/**=anon /styles/**=anon <!-- /** = authc 所有的URL都要验证 --> /**=authc
注意:登录页面login.jsp中的用户名和密码控件的name必须是username和password,这是shiro框架源码要求的(也可以换成别的名字,需要在applicationContext-shiro.xml中配置即可)
运行:在浏览器地址栏直接输入http://localhost:8080/ssm_shiro/first.action回车就会被shiro拦截器拦截到login.action到登录页面:
这时候如果输入自定义的realm中的模拟数据库的用户名zhang和密码123就可以登录,其他都会被抛出异常页面(账号不存在,密码不存在等等)
-------------------------------------------------------------------------
需求3:
3.1.登录成功后,在页头显示“欢迎XXX”
3.2.把该用户的菜单显示出来
----------------------------------------
一、修改自定义Realm
@Autowired
private SysService sysService;
/** * 认证 token:用户输入的令牌,可以是字符串,也可以是对象 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 从token中获取用户名 String username = (String) token.getPrincipal(); // 根据用户输入的用户名从数据库中查找用户信息(密码),这里只是模拟的静态数据 // 如果查不到就返回null... // 假设数据库中的用户名是PeterDB if (!"zhangsan".equals(username)) { return null; // 返回null之后,下面的代码都不执行 } // 如果查到就返回password String password = "123"; // 认证通过用ActiveUser接收,这里先全部写成静态的数据,等到后面再一次改成动态的 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid("zhangsan"); activeUser.setUsercode("zhangsan"); // 获取菜单 List<SysPermission> menus = null; try { menus = sysService.findMenuListByUserId("zhangsan"); } catch (Exception e) { e.printStackTrace(); } activeUser.setMenus(menus); // 返回认证信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( activeUser, password, this.getName()); return simpleAuthenticationInfo; } // Realm的名称(自定义),可以不定义 @Override public void setName(String name) { super.setName("customRealm"); }
这时候登录,并没有菜单,因为登录成功后浏览器地址是http://localhost:8080/ssm_shiro/first.action,而first.action中并没有将菜单添加到jsp,修改first.action
FirstAction.java
@Controller public class FirstAction { //系统首页 @RequestMapping("/first") public String first(Model model)throws Exception{
// 获取通过认证的用户 Subject subject = SecurityUtils.getSubject(); ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
// 带到页面 model.addAttribute("activeUser", activeUser); return "/first"; } }
这时候有菜单了,但是欢迎标题还没有,是因为在认证通过之后,并没有将用户名设置到activeUser中,所以在jsp页面用EL表达式没有获取到用户的信息;
修改自定义Realm:CustomRealm.java
activeUser.setUsername("张三");
-------------------------------------------------
需求4:把自定义Realm中的用户信息改成动态的,并使用md5散列
/** * 认证 token:用户输入的令牌,可以是字符串,也可以是对象 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 从token中获取用户名 String usercode = (String) token.getPrincipal(); SysUser sysUser = null; try { sysUser = sysService.findSysUserByUserCode(usercode); } catch (Exception e1) { e1.printStackTrace(); } // 如果查不到就返回null... // 假设数据库中的用户名是PeterDB if (sysUser == null) { return null; // 返回null之后,下面的代码都不执行 } // 如果查到就返回password String password = sysUser.getPassword(); // 盐 String salt = sysUser.getSalt(); // 认证通过用ActiveUser接收,这里先全部写成静态的数据,等到后面再一次改成动态的 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid(sysUser.getId()); activeUser.setUsercode(sysUser.getUsercode()); activeUser.setUsername(sysUser.getUsername()); // 获取菜单 List<SysPermission> menus = null; try { menus = sysService.findMenuListByUserId(sysUser.getId()); } catch (Exception e) { e.printStackTrace(); } activeUser.setMenus(menus); // 返回认证信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( activeUser, password, ByteSource.Util.bytes(salt), this.getName()); return simpleAuthenticationInfo; }
以上使用了md5进行加密,所以还需要在spring中配置凭证匹配器:
applicationContext-shiro.xml
<!-- 自定义 realm --> <bean id="customRealm" class="cn.itcast.ssm.realm.CustomRealm"> <!-- 将凭证匹配器设置到自定义Realm中 --> <property name="credentialsMatcher" ref="credentialsMatcher"/> </bean> <!-- 凭证匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 使用什么算法 --> <property name="hashAlgorithmName" value="md5"/> <!-- 散列几次 --> <property name="hashIterations" value="1"/> </bean>
原始密码111111,加盐hello进行md5加密后的密码是:4ab06e04b551df5f06878a1713a7a090
这时候输入zhangsan,111111,登录成功!
-------------------------------------------------------------------------------------
需求5:授权---从数据库授权
CustomRealm.java:
/** * 授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 授权是在认证通过后的操作,principals是认证通过后返回的SimpleAuthenticationInfo对象的第一个参数 ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal(); // 开发中要从数据库中获取 List<SysPermission> permissionList = null; List<String> permissions = null; try { permissionList = sysService.findPermissionListByUserId(activeUser.getUserid()); if (permissionList != null) { permissions = new ArrayList<String>(); for (SysPermission permission : permissionList) { permissions.add(permission.getPercode()); } } } catch (Exception e) { e.printStackTrace(); } // 返回权限信息 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.addStringPermissions(permissions); return simpleAuthorizationInfo; }
需求6:使用注解的方式和shiro标签的方式配置
以上在applicatonContext-shiro.xml中配置url比较麻烦,因为要一个一个的配置,也不实际:
7。使用下面的注解方式进行授权:
因为shiro是基于aop代理的,所以需要在springmvc.xml(因为在这个文件集中扫描controller,所以配置到这里)中开启aop注解:
<!-- 开启aop,对类代理:这是spring的配置 --> <aop:config proxy-target-class="true"/> <!-- 开启shiro注解支持:这个才是shiro的配置 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean>
一下是shiro标签:
在itemsLIst.jsp中添加:
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<td> <!-- 有item:update权限才能进行修改,相当于if(hasPermission(item:update)) --> <shiro:hasPermission name="item:update"> <a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a> </shiro:hasPermission> </td>
以上的shiro标签,如果跟踪源代码就会发现,Jsp页面有多少次循环,ItemsController的修改商品的方法就会执行多少次,并且这个方法要多次去查询数据库,数据库的
压力大,所以这里要使用缓存。但是基于注解@RequiresPermissions和shiro标签的方式进行授权确实会比较方便。开发中建议使用这种方式。
----------------------------------------------------------------
需求8:shiro的缓存(针对上面授权的频繁查询数据库的问题,这里要使用shiro缓存来解决)
shiro框架中的认证信息的缓存默认是关闭的(因为信息不大,只要一次认证通过就即刻,不会多次操作数据库),而授权的信息是很大的(可能需要多次频繁操作
数据库),所以shiro框架对授权信息的缓存默认是开启的。
shiro缓存的原理:
加入jar包:
配置缓存管理器:cacheManager,修改applicationContext-shiro.xml
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 自定义Realm --> <property name="realm" ref="customRealm" /> <!-- 缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 缓存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/> </bean>
创建shiro-ehcache.xml,这个文件配置了缓存的参数:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!--diskStore:缓存数据持久化的目录 地址 --> <diskStore path="F:\develop\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
启动测试:在自定义Realm的认证方法中打断点测试
(1)登录进去,点击:商品管理,进入断点测试,执行完,查询出商品列表,这时候再次点击商品管理,不会进入断点测试,因为商品列表的数据已经被缓存放在内存中,
直接从缓存中获取商品列表数据
(2)当“退出系统”(属于正常退出),再次进入又会从数据库中获取信息
(3)如果直接关闭浏览器(属于不正常退出),重新打开一个窗口进入,也会从数据库中获取信息
----------------------------
总结以上操作,不管用户是否正常退出系统,shiro都会清空缓存。
问题:如果管理员修改了用户的某个权限,只要用户不退出系统,或不关闭浏览器,修改的权限就无法立即生效(在缓存时间内)!
需求9:管理员一旦修改了用户的某个权限,要立即生效,即使用户不退出系统和不关闭浏览器,也要立即生效!
做法:在权限修改(在service中修改)完成后,手动编程,调用realm的clearCache方法清除缓存
注意:实际开发中以下方法要写在service中,这里为了方便就直接调用一个controller清空缓存
在CustomRealm.java中添加:
// 清除缓存 public void clearCached() { PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals(); super.clearCache(principals); }
创建一个controller,只是用于测试,并没有什么卵用:ClearCache.java
package cn.itcast.ssm.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import cn.itcast.ssm.realm.CustomRealm;
// 清空缓存的controller,只是测试,并没有什么卵用
@Controller
public class ClearCache {
// 注入Realm
@Autowired
private CustomRealm customRealm;
// 清空缓存
@RequestMapping("/clearShiroCache")
public String clearShiroCache() {
// 正常开发中,这个方法要写在service中
customRealm.clearCached();
return "success";
}
}
启动测试:
第一次进入系统,点击商品管理,会查询数据库,再次点击商品管理,不会查询数据库,这时候如果直接在浏览器的地址栏中输入:
http://localhost:8080/ssm_shiro/clearShiroCache.action,回车,就会清空缓存,后退浏览器,回到系统主页,这时候再点击商品管理,又会查找数据库,因为缓存已被清空
------------------------------------------------------------
需求10:会话的实现
在applicationContext-shiro.xml中添加shiro的会话管理器
<!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效时长,单位:毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 删除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean>
注入:
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 自定义Realm -->
<property name="realm" ref="customRealm" />
<!-- 缓存管理器 -->
<property name="cacheManager" ref="cacheManager"/>
<!-- 会话管理器 -->
<property name="sessionManager" ref="sessionManager"/>
</bean>
启动测试:
进入系统,如果以上配置的<property name="globalSessionTimeout" value="5000"/>,即5秒后session将失效,这时候再刷新页面就会被拦截到登录页面:
需求11:验证码的实现
(1)自定义FormAuthenticationFilter,CustomFormAuthenticationFilter.java
package cn.itcast.ssm.realm; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; // 自定义的FormAuthenticationFilter,认证之前实现验证码校验 public class CustomFormAuthenticationFilter extends FormAuthenticationFilter { // 原FormAuthenticationFilter的认证方法,这里修改将它改写,使得在认证之前进行验证码的校验 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { // 在这里进行验证码的校验 // 从session中获取正确的验证码(即页面生成的验证码) HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpSession session = httpServletRequest.getSession(); String validateCode = (String) session.getAttribute("validateCode"); // 获取用户输入的验证码 String randomcode = httpServletRequest.getParameter("randomcode"); if (randomcode != null && validateCode != null && !randomcode.equalsIgnoreCase(validateCode)) { // 如果校验失败,将验证码错误的失败信息,通过shiroLoginFailure设置到request域中,将来在登录Controller中获取 httpServletRequest.setAttribute("shiroLoginFailure", "randomcodeError"); // 返回true,拒绝访问,不再进行后面的用户名和密码的校验 return true; } return super.onAccessDenied(request, response); } }
修改LoginController.java:
(2)配置自定义的formAuthenticationFilter,在applicationContext-shiro.xml中配置:
<!-- 配置自定义的formAuthenticationFilter,如果不配置,username和password的名称将使用shiro的默认配置 --> <bean id="formAuthenticationFilter" class="cn.itcast.ssm.realm.CustomFormAuthenticationFilter"> <!-- 表单中账号的input的name名称 --> <property name="usernameParam" value="username"/> <!-- 表单中密码的input的name名称 --> <property name="passwordParam" value="password"/> </bean>
页面的验证码:
<TR>
<TD>验证码:</TD>
<TD><input id="randomcode" name="randomcode" size="8" /> <img
id="randomcode_img" src="${baseurl}validatecode.jsp" alt=""
width="56" height="20" align='absMiddle' /> <a
href=javascript:randomcode_refresh()>刷新</a></TD>
</TR>
启动测试:
发现这个验证码的jsp页面被shiro框架拦截了,在applicationContext-shiro.xml中配置静态资源:
/validatecode.jsp=anon
再一次测试:
注意:applicationContext-shiro.xml中的session的失效时长改成600000,否则按以前的5000即5秒失效就会测试不成功,因为session中刚放入的验证码由于5秒后失效了
导致验证码校验失败!
以上只有用户名和密码和验证码都正确的情况下才能进入系统,三者校验的顺序:验证码-->用户名-->密码
如果验证码都校验失败,那么就没有必要去校验用户名和密码了;
需求12:记住我的实现
1.POJO类要实现序列化接口
2.在applicationContext-shiro.xml中配置cookie管理器
<!-- 记住我cookie管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="remenberMeCookie"/> </bean> <!-- 记住我cookie --> <bean id="remenberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <!-- remenberMe是cookie的名字 --> <constructor-arg value="remenberMe"/> <!-- 记住我的cookie生效时间,30天,单位:秒 --> <property name="maxAge" value="2592000"/> </bean>
将remenberMeManager注入到SecurityManager中
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 自定义Realm -->
<property name="realm" ref="customRealm" />
<!-- 缓存管理器 -->
<property name="cacheManager" ref="cacheManager"/>
<!-- 会话管理器 -->
<property name="sessionManager" ref="sessionManager"/>
<!-- 记住我 -->
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
3.写页面
<tr> <td></td> <td><input type="checkbox" name="remenberMe"/> 记住我</td> </tr>
4.在applicationContext-shiro.xml中的表单认证bean中注入rememberMe
<!-- 配置自定义的formAuthenticationFilter,如果不配置,username和password的名称将使用shiro的默认配置 -->
<bean id="formAuthenticationFilter" class="cn.itcast.ssm.realm.CustomFormAuthenticationFilter">
<!-- 表单中账号的input的name名称 -->
<property name="usernameParam" value="username"/>
<!-- 表单中密码的input的name名称 -->
<property name="passwordParam" value="password"/>
<!-- 记住我, input的name名称 -->
<property name="rememberMeParam" value="remenberMe"/>
</bean>
启动测试:没有问题
但是退出系统后,直接在浏览器地址栏输入某些url(记住我的url),应该直接跳转到那个url(无需登录),但是现在不行,解决方法:
使用UserFilter,将记住我即可访问的URL地址配置让UserFilter拦截。