讲前必读
第一节:shiro授权
1. 重点:讲解授权流程并实现对用户授权。
2. 课程实际内容
a) 简介:回顾shiro架构及相关对象以及认证流程
b) 重点:shiro授权流程
c) 简介:授权方式
d) 重点:授权实现
e) 简介:测试
3. 重点:课堂总结
a) 授权实现
练习20分钟
第二节:自定义Realm实现授权
1. 重点:自定义Realm实现授权。
2. 课程实际内容
a) 简介:配置文件实现授权的缺点
b) 重点:通过自定义Realm实现动态授权
c) 重点:自定义Realm实现授权步骤
d) 简介:测试
3. 重点:课堂总结
a) 自定义Realm实现授权步骤
第三节:shiro与项目集成开发
1. 重点:shiro整合spring web要点
2. 课程实际内容
a) 简介:shiro整合web项目的必要性
b) 重点:在项目整合shiro
c) 简介:shiro过滤器
d) 重点:通过shiro实现登录
e) 简介:通过shiro实现退出
3. 重点:课堂总结
a) Shiro整合项目的步骤
第四节:在集成项目中实现认证及授权
1. 重点:如何在集成项目实现授权,Controller中如何控制,jsp中如何控制
2. 课程实际内容
a) 重点:认证实现
b) 重点:修改自定义Realm
c) 重点:权限注解控制
d) 重点:jsp标签控制
3. 重点:课堂总结
a) 项目中认证和授权的实现步骤及对比之前学习的认证和授权
练习30分钟
第五节:缓存管理、验证码及记住我实现
1. 重点:缓存管理的必要性及缓存管理的实现
2. 课程实际内容
a) 简介:为什么需要缓存管理
b) 重点:缓存管理的实现
c) 重点:验证码实现
d) 简介:记住我实现
3. 重点:课堂总结
a) 总结缓存管理的好处。
第一节课备课参考
核心脉络
授权在整个权限管理中的重要性,shiro中的授权流程,如何实现授权,如何在自定义Realm中实现授权。
重点:
1. 在自定义Realm中实现授权
难点:
1. 在自定义Realm中实现授权
互动:在前一天的课程中,实现了权限管理中的身份认证,接下来讨论另外一个非常重要的点------授权。
授权
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作
等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、
角色(Role)。
关键对象介绍
主体
主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访
问相应的资源。
资源
在应用中用户可以访问的任何东西,比如访问JSP 页面、查看/编辑某些数据、访问某个业
务方法、打印文本等等都是资源。用户只要授权后才能访问。
权限
安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的
权力。即权限表示在应用中用户能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)打印文档等等。。。
角色
角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权
限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总
监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。
授权流程
流程如下:
1、首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而
SecurityManager接着会委托给Authorizer;
2、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过
PermissionResolver把字符串转换成相应的Permission实例;
3、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的
角色/权限;
4、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给
ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否
则返回false表示授权失败。
授权方式
Shiro支持三种方式的授权:
编程式:通过写if/else授权代码块完成:
Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) { //有权限 } else { //无权限 } |
注解式:通过在执行的Java方法上放置相应的注解完成:
@RequiresRoles("admin") public void hello() { //有权限 } |
没有权限将抛出相应的异常;
JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:
<shiro:hasRole name="admin"> <!— 有权限—> </shiro:hasRole> |
授权实现
在ini配置文件配置用户拥有的角色及角色-权限关系(shiro-permission.ini)
[users] zhangsan=1111,role1,role2 lisi=1111,role1 [roles] role1=user:create,user:update role2=user:create,user:delete |
规则:“用户名=密码,角色1,角色2” “角色=权限1,权限2”,即首先根据用户名找
到角色,然后根据角色再找到权限;即角色是权限集合;Shiro 同样不进行权限的维护,需
要我们通过Realm返回相应的权限信息。只需要维护“用户——角色”之间的关系即可。
权限字符串的规则是:“资源标识符:操作:资源实例标识符”,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
例子:
用户创建权限:user:create,或user:create:*
用户修改实例001的权限:user:update:001
用户实例001的所有权限:user:*:001
实现代码
/** * * @author邹波 * @version 1.0 * @date 2016-1-21 */ public class ShiroTest { //用户登录和退出 @Test public void testPermission(){ // 构建SecurityManager工厂,IniSecurityManagerFactory可以从ini文件中初始化SecurityManager环境 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission.ini"); //通过工厂获得SecurityManager实例 SecurityManager securityManager = factory.getInstance(); //将securityManager设置到运行环境中 SecurityUtils.setSecurityManager(securityManager); //获取subject实例 Subject subject = SecurityUtils.getSubject(); //创建用户名,密码身份验证Token UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "1111"); try { //登录,即身份验证 subject.login(token); } catch (AuthenticationException e) { e.printStackTrace(); //身份认证失败 } // 用户认证状态 boolean isAuthenticated = subject.isAuthenticated(); System.out.println("用户认证状态:" + isAuthenticated);
//判断拥有角色:role1 Assert.assertTrue(subject.hasRole("role1")); //判断拥有角色:role1 and role2 Assert.assertTrue(subject.hasAllRoles(Arrays.asList("role1", "role2"))); //判断拥有角色:role1 and role2 and !role3 boolean[] result = subject.hasRoles(Arrays.asList("role1", "role2", "role3")); Assert.assertEquals(true, result[0]); Assert.assertEquals(true, result[1]); Assert.assertEquals(false, result[2]);
//判断拥有权限:user:create Assert.assertTrue(subject.isPermitted("user:create")); //判断拥有权限:user:update and user:delete Assert.assertTrue(subject.isPermittedAll("user:update", "user:delete")); //判断没有权限:user:view Assert.assertFalse(subject.isPermitted("user:view")); } }
|
第二节课备课参考
核心脉络
通过自定义Realm实现动态授权。
重点:
1. 自定义Realm实现
难点:
1. 自定义Realm实现
自定义Realm实现授权
与上边认证自定义realm一样,大部分情况是要从数据库获取权限数据,这里直接实现基于资源的授权。
UserRealm实现代码
/** * 自定义Realm实现 * @author邹波 * @version 1.0 * @date 2016-1-21 */ public class UserRealm extends AuthorizingRealm { @Override public String getName() { return "UserRealm"; } //用于认证 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { //从token中获取身份信息 String username = (String)token.getPrincipal(); //根据用户名到数据库中取出用户信息 如果查询不到 返回null String password = "1111";//假如从数据库中获取密码为1111 //返回认证信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, this.getName()); return simpleAuthenticationInfo; } //用于授权 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { //获取身份信息 String username = (String)principals.getPrimaryPrincipal(); //根据身份信息获取权限数据 //模拟 List<String> permissions = new ArrayList<String>(); permissions.add("user:save"); permissions.add("user:delete"); //将权限信息保存到AuthorizationInfo中 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for(String permission:permissions){ simpleAuthorizationInfo.addStringPermission(permission); } return simpleAuthorizationInfo; } } |
增加了红色部分代码
配置文件
[main] #自定义 realm userRealm=cn.siggy.realm.UserRealm #将realm设置到securityManager securityManager.realms=$userRealm |
测试代码
/** * 自定义Realm实现 * @author邹波 * @version 1.0 * @date 2016-1-21 */ public class UserRealm extends AuthorizingRealm { @Override public String getName() { return "UserRealm"; } //用于认证 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { //从token中获取身份信息 String username = (String)token.getPrincipal(); //根据用户名到数据库中取出用户信息 如果查询不到 返回null String password = "1111";//假如从数据库中获取密码为1111 //返回认证信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, this.getName()); return simpleAuthenticationInfo; } //用于授权 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { //获取身份信息 String username = (String)principals.getPrimaryPrincipal(); //根据身份信息获取权限数据 //模拟 List<String> permissions = new ArrayList<String>(); permissions.add("user:save"); permissions.add("user:update"); permissions.add("user:delete"); //将权限信息保存到AuthorizationInfo中 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for(String permission:permissions){ simpleAuthorizationInfo.addStringPermission(permission); } return simpleAuthorizationInfo; } } |
测试
第三节课备课参考
核心脉络
在之前的学习中,虽然学习了shiro架构中非常重要的几块知识,但是只是在java SE项目中使用。那么如何在集成项目中使用shiro,是接下来我们要去讨论的问题。
重点:
1. 在spring web中整合shiro
难点:
1. 在spring web中整合shiro
互动:在这之前我们把shiro的相关技术点已经弄完了。那么接下来我们看看在项目中如何使用shiro。
shiro与项目集成开发
shiro与spring web项目整合
shiro与springweb项目整合在“基于url拦截实现的工程”基础上整合,基于url拦截实现的工程的技术架构是springmvc+mybatis,整合注意两点:
1、shiro与spring整合
2、加入shiro对web应用的支持
取消原springmvc认证和授权拦截器
去掉springmvc.xml中配置的LoginInterceptor和PermissionInterceptor拦截器。
加入shiro的 jar包
web.xml添加shiro Filter
<!-- shiro过虑器,DelegatingFilterProxy通过代理模式将spring容器中的bean和filter关联起来 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <!-- 设置true由servlet容器控制filter的生命周期 --> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> <!-- 设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean--> <init-param> <param-name>targetBeanName</param-name> <param-value>shiroFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
applicationContext-shiro.xml
<!-- 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" /> <!-- 认证成功统一跳转到index.do,建议不配置,shiro认证成功自动到上一个请求路径 --> <property name="successUrl" value="/index.do"/> <!-- 通过unauthorizedUrl指定没有权限操作时跳转页面--> <property name="unauthorizedUrl" value="/refuse.do" /> <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 --> <property name="filterChainDefinitions"> <value> <!-- /** = authc 所有url都必须认证通过才可以访问
/refuse.do=anon--> /login.do=authc /logout=logout <!-- /user/list.do=perms[role:list] --> /** = anon <!-- /** = anon所有url都可以匿名访问 -->
</value> </property> </bean> <!-- 安全管理器定义 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm"></property> <property name="sessionManager" ref="sessionManager"></property> </bean> <!-- 自定义Realm --> <bean id="customRealm" class="cn.sxt.shiro.realm.CustomRealm"> <!-- 定义凭证匹配器 --> <property name="credentialsMatcher" ref="credentialsMatcher"></property> </bean> |
securityManager:这个属性是必须的。
loginUrl:没有登录认证的用户请求将跳转到此地址进行认证,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。
unauthorizedUrl:没有权限默认跳转的页面。
自定义realm
此realm先不从数据库查询权限数据,当前需要先将shiro整合完成,在上边章节定义的realm基础上修改。
public class CustomRealm extends AuthorizingRealm{ @Autowired private UserService userService; @Autowired private PermissionService permissionService; @Override public String getName() { return "CustomRealm"; } /** * 完成认证 * */ protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { //完成认证信息验证 String userName = token.getPrincipal().toString(); User currentUser=null; try { currentUser = userService.login(userName); //设置菜单 currentUser.setMenus(permissionService.findMenuByUser(currentUser.getId())); //设置权限 currentUser.setPermissions(permissionService.findPermissionByUser(currentUser.getId())); } catch (Exception e) { e.printStackTrace(); } if(currentUser==null){ return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currentUser, currentUser.getPwd(), ByteSource.Util.bytes(currentUser.getSalt()),getName()); return info; }
/** * 完成授权 * */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取用户名 User currentUser = (User)principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set<String> permission = new HashSet<String>(); for(Permission p:currentUser.getPermissions()){ permission.add(p.getPercode()); } info.addStringPermissions(permission); return info; } }
|
登录
// 用户登陆提交 @RequestMapping("/login") public String loginsubmit(Model model, HttpServletRequest request) throws Exception {
// shiro在认证过程中出现错误后将异常类路径通过request返回 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 if("randomCodeError".equals(exceptionClassName)){ throw new CustomException("验证码错误"); } else{ throw new Exception();//最终在异常处理器生成未知错误 } } return"login"; } |
首页
由于session由shiro管理,需要修改首页的controller方法,将session中的数据通过model传到页面。
//系统首页 @RequestMapping("/index") public ModelAndView index(ModelMap map){ Subject subject = SecurityUtils.getSubject(); User currentUser = (User)subject.getPrincipal(); map.addAttribute("currentUser", currentUser); return new ModelAndView("index"); } |
退出
由于使用shiro的sessionManager,不用开发退出功能,使用shiro的logout拦截器即可。
<!-- 退出拦截,请求logout.action执行退出操作 --> /logout.action = logout |
无权限refuse.jsp
当用户无操作权限,shiro将跳转到refuse.jsp页面。
第四节课备课参考
核心脉络
在上一节的内容中,将shiro整合进了集成项目。实现了登录,接下来实现在集成项目中认证和授权的实现。
重点:
1. 在集成项目中实现权限控制
难点:
1. 在集成项目中实现权限控制
认证
添加凭证匹配器
添加凭证匹配器实现md5加密校验。
修改applicationContext-shiro.xml:
<!-- 自定义Realm --> <bean id="customRealm" class="cn.sxt.shiro.realm.CustomRealm"> <!-- 定义凭证匹配器 --> <property name="credentialsMatcher" ref="credentialsMatcher"></property> </bean> <!-- 定义凭证匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5"></property> <property name="hashIterations" value="1"></property> </bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> |
修改realm认证方法
修改realm代码从数据库中查询用户身份信息,将sysService注入realm。
public class CustomRealm extends AuthorizingRealm{ @Autowired private UserService userService; @Autowired private PermissionService permissionService; @Override public String getName() { return "CustomRealm"; } /** * 完成认证 * */ protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { //完成认证信息验证 String userName = token.getPrincipal().toString(); User currentUser=null; try { currentUser = userService.login(userName); //设置菜单 currentUser.setMenus(permissionService.findMenuByUser(currentUser.getId())); //设置权限 currentUser.setPermissions(permissionService.findPermissionByUser(currentUser.getId())); } catch (Exception e) { e.printStackTrace(); } if(currentUser==null){ return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currentUser, currentUser.getPwd(), ByteSource.Util.bytes(currentUser.getSalt()),getName()); return info; }
} |
授权
修改realm授权方法
修改realm代码从数据库中查询权限信息,将sysService注入realm。
public class CustomRealm extends AuthorizingRealm{ @Autowired private UserService userService; @Autowired private PermissionService permissionService; @Override public String getName() { return "CustomRealm"; } /** * 完成授权 * */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取用户名 User currentUser = (User)principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); Set<String> permission = new HashSet<String>(); for(Permission p:currentUser.getPermissions()){ permission.add(p.getPercode()); } info.addStringPermissions(permission); return info; }
} |
对controller开启AOP
在springmvc.xml中配置shiro注解支持,可在controller方法中使用shiro注解配置权限:
<!-- 开启aop,对类代理 --> <aop:config proxy-target-class="true"></aop:config> <!-- 开启shiro注解支持 --> <bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> |
权限注解控制
商品查询controller方法添加权限(item:query):
// 查询商品列表 @RequestMapping("/queryItem") @RequiresPermissions("item:query") public ModelAndView queryItem() throws Exception { |
上边代码@RequiresPermissions("item:query")表示必须拥有“item:query”权限方可执行。
同理,商品修改controller方法添加权限(item:update):
@RequestMapping(value = "/editItem") @RequiresPermissions("item:update") public String editItem(@RequestParam(value = "id", required = true) Integer id, Model model) throws Exception
// 商品修改提交 @RequestMapping("/editItemSubmit") @RequiresPermissions("item:update") public String editItemSubmit(@ModelAttribute("item") Items items,BindingResult result, MultipartFile pictureFile,Model model,HttpServletRequest request) throws Exception
|
jsp标签控制
标签介绍
Jsp页面添加:
<%@tagliburi="http://shiro.apache.org/tags" prefix="shiro"%>
标签名称 | 标签条件(均是显示标签内容) |
<shiro:authenticated> | 登录之后 |
<shiro:notAuthenticated> | 不在登录状态时 |
<shiro:guest> | 用户在没有RememberMe时 |
<shiro:user> | 用户在RememberMe时 |
<shiro:hasAnyRoles name="abc,123" > | 在有abc或者123角色时 |
<shiro:hasRole name="abc"> | 拥有角色abc |
<shiro:lacksRole name="abc"> | 没有角色abc |
<shiro:hasPermission name="abc"> | 拥有权限资源abc |
<shiro:lacksPermission name="abc"> | 没有abc权限资源 |
<shiro:principal> | 显示用户身份名称 |
<shiro:principalproperty="username"/> 显示用户身份中的属性值
jsp页面添加标签
如果有商品修改权限页面显示“修改”链接。
<shiro:hasPermission name="item:update"> <a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a> </shiro:hasPermission> |
第五节课备课参考
核心脉络
Shiro除了提供认证授权外还提供验证码,记住我等其他常见功能。
验证码
自定义FormAuthenticationFilter
需要在验证账号和名称之前校验验证码。
public class MyFormAuthenticationFilter extends FormAuthenticationFilter { protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
// 校验验证码 // 从session获取正确的验证码 HttpSession session = ((HttpServletRequest)request).getSession(); //页面输入的验证码 String randomcode = request.getParameter("randomcode"); //从session中取出验证码 String validateCode = (String) session.getAttribute("validateCode"); if (randomcode!=null && validateCode!=null) { if (!randomcode.equals(validateCode)) { // randomCodeError表示验证码错误 request.setAttribute("shiroLoginFailure", "randomCodeError"); //拒绝访问,不再校验账号和密码 return true; } return super.onAccessDenied(request, response, mappedValue); } }
|
FormAuthenticationFilter配置
修改applicationContext-shiro.xml中对FormAuthenticationFilter的配置。
n 在shiroFilter中添加filters:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="filters"> <map> <!-- FormAuthenticationFilter是基于表单认证的过虑器 --> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> |
n formAuthenticationFilter定义
<!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --> <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.MyFormAuthenticationFilter "> <!-- 表单中账号的input名称 --> <property name="usernameParam" value="username" /> <!-- 表单中密码的input名称 --> <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> |
配置validatecode.jsp匿名访问
修改applicationContext-shiro.xml:
记住我
用户登陆选择“自动登陆”本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。
用户身份实现java.io.Serializable接口
向cookie记录身份信息需要用户身份信息对象实现序列化接口,如下:
配置rememberMeManager
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager"/> <!-- 记住我 --> <property name="rememberMeManager" ref="rememberMeManager"/> </bean> <!-- rememberMeManager管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 记住我cookie --> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <!-- 记住我cookie生效时间30天 --> <property name="maxAge" value="2592000" /> </bean> |
FormAuthenticationFilter配置
修改formAuthenticationFitler添加页面中“记住我checkbox”的input名称:
<bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.MyFormAuthenticationFilter"> <!-- 表单中账号的input名称 --> <property name="usernameParam" value="usercode" /> <!-- 表单中密码的input名称 --> <property name="passwordParam" value="password" /> <property name="rememberMeParam" value="rememberMe"/> </bean> |
登陆页面
在login.jsp中添加“记住我”checkbox。
<TR> <TD></TD> <TD> <input type="checkbox" name="rememberMe" />自动登陆 </TD> </TR> |