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/...