rememberMe
流程原理研究rememberme
isRemembered()==true
(若是上一次设置了rememberme
, 本次登陆是不会触发action
中的login()
的方法的, 即会直接进入登陆状态. 这里为了演示, 强行进入login()
方法).
- 通过
shiro
的login()
则表示为认证登陆的. 就是说authentication==true
. 访问权限最高.rememberMe==true
, 则将不会进入任何action. 能够访问全部user
控制的页面或路径. 但不能访问authc
控制的.
可是authentication=false
. 这里有个关键点:css
subject.isAuthenticated()==true,
则subject.isRemembered()==false;
反之同样
下图所示, authentication=false
, 而且可以principle
不为空, 可以获取用户信息.web
另外对于过滤器,通常这样使用:spring
(isRemembered()==true or isAuthenticated()==true)
经过便可访问成功;authc
拦截器便可,authc
拦截器会判断用户是不是经过Subject.login(isAuthenticated()==true)
登陆的,若是是才放行,不然会跳转到登陆页面叫你从新登陆。rememberMe
的cookie
shiro
自动对用户对象序列化并加密. 当得到请求时, 可以获取反序列化且解密以后的用户对象。rememberMe==false
, 将会自动清空rememberMe cookie.以下图, 在设置rememberMe==false
的前提下, 以前的rememberMe cookie已经不见了.apache
项目重启后(排除缓存影响). 强行访问action
, 可以获取user
对象.缓存
调用shiro
的logout()
方法, 即消除自动登陆功能.安全
引入maven
坐标.cookie
<!-- 权限控制 框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>${shiro.version}</version> </dependency>
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiro框架相关 --> <!--配置shiro的过滤器工厂bean--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--注入安全管理器--> <property name="securityManager" ref="securityManager"/> <!--注入相关页面访问url--> <property name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/index.jsp"/> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> <!--注入url拦截规则--> <property name="filterChainDefinitions"> <value> /css/**=anon /js/**=anon /images/**=anon /validatecode.jsp*=anon /userAction_login.action=anon /customerAction_login.action=anon /info.jsp*=anon /courierAction_pageQuery*=perms["courier:list"] /pages/base/courier.jsp*=perms["courier:list"] /** = user /pay/** = authc </value> </property> </bean> <!--注册安全管理对象--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> <!--注入缓存管理器--> <property name="cacheManager" ref="cacheManager"/> </bean> <!--自定义realm--> <bean id="userRealm" class="com.sykd.bos.service.system.realm.UserRealm"></bean> <!--注册缓存管理器: 这里用ehcache插件(已被shiro集成)--> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <!--指定ehcache配置文件--> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean>
realm
public class UserRealm extends AuthorizingRealm { @Autowired private UserDao userDao; @Autowired private PermissionDao permissionDao; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; // !这里的username可能并非真正的username, 多是手机号或者其余能够做为登陆凭证的字段! String username = token.getUsername(); User u = userDao.findByUsernameOrTelephone(username, username); if (u == null) { return null; } AuthenticationInfo info = new SimpleAuthenticationInfo(u, u.getPassword(), this.getName()); return info; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取当前用户 User user = (User) principalCollection.getPrimaryPrincipal(); //内置用户:授予全部权限 List<Permission> permissions = null; if (user != null && user.getUsername().equals("admin")) { permissions = permissionDao.findAll(); } else { // 其余普通用户:查出该用户对应的全部权限 permissions = permissionDao.findByUserId(user.getId()); } // 受权 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Permission p : permissions) { info.addStringPermission(p.getKeyword()); } return info; } }
action
@Action(value = "userAction_login") public String login() throws UnsupportedEncodingException { Log.begin(); String validateCode_ser = (String) ServletActionContext.getRequest().getSession().getAttribute("validateCode"); Subject subject; if (StringUtils.isNotBlank(this.validateCode) && this.validateCode.equals(validateCode_ser)) { subject = SecurityUtils.getSubject(); // 不论用户输入的是用户名仍是手机号, 前台标签统一用username接收 UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); //[[ADD 2018-1-9 14:44:01 // 设置是否'记住我' rememberme = rememberme == null ? false : rememberme; //null=>false token.setRememberMe(rememberme); // ]] try { subject.login(token); if (rememberme) LOG.info("用户【{}】自动登陆----{}", "天王", String.valueOf(System.currentTimeMillis())); } catch (AuthenticationException e) { e.printStackTrace(); return LOGIN; } } else { this.addActionError("输入的验证码有误!"); return ERROR; }//end if return "home"; }
注意: 默认cookie会保存一年. 这个有点太长了, 一般须要缩短.框架
主要是spring
配置的区别, 须要: 1. 配置自定义cookie; 2. 注入给rememberMeManager
; 3. 将rememberMeManager
注入给securityManager
.jsp
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiro框架相关 --> <!--配置shiro的过滤器工厂bean--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--注入安全管理器--> <property name="securityManager" ref="securityManager"/> <!--注入相关页面访问url--> <property name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/index.jsp"/> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> <!--注入url拦截规则--> <property name="filterChainDefinitions"> <value> /css/**=anon /js/**=anon /images/**=anon /validatecode.jsp*=anon /userAction_login.action=anon /customerAction_login.action=anon /info.jsp*=anon /courierAction_pageQuery*=perms["courier:list"] /pages/base/courier.jsp*=perms["courier:list"] /** = user /pay/** = authc </value> </property> </bean> <!--注册安全管理对象--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> <!--注入缓存管理器--> <property name="cacheManager" ref="cacheManager"/> <!--注入rememberMe cookie管理器--> <property name="rememberMeManager" ref="rememberMeManager"/> </bean> <bean id="userRealm" class="com.sykd.bos.service.system.realm.UserRealm"></bean> <!--手动指定cookie--> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe"/> <property name="httpOnly" value="true"/> <property name="maxAge" value="604800"/><!-- 7天 --> </bean> <!-- rememberMe管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <!--注入自定义cookie(主要是设置寿命, 默认的一年太长)--> <property name="cookie" ref="rememberMeCookie"/> </bean> <!--注册缓存管理器: 这里用ehcache插件(已被shiro集成)--> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <!--指定ehcache配置文件--> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> </bean>
这种方式须要在spring
中配置不少参数. 很繁琐. 可是功能齐全. 若是只想实现简单的自动功能, 能够参照简单实现.
本部分spring
配置可参见: 第十三章 RememberMe——《跟我学Shiro》maven
参考资料:
[1] http://jinnianshilongnian.ite...
[2] http://blog.icoolxue.com/shir...
[3] http://blog.csdn.net/lhacker/...