Apache Shiro(七)——Shiro的RememberMe功能
一、概述
Shiro 提供了記住我(RememberMe)的功能,比如訪問如淘寶等一些網站時,關閉了瀏覽器,下次再開啟時還是能記住你是誰,下次訪問時無需再登入即可訪問,基本流程如下:
1、首先在登入頁面選中 RememberMe 然後登入成功;如果是瀏覽器登入,一般會把 RememberMe 的Cookie 寫到客戶端並儲存下來;
2、關閉瀏覽器再重新開啟;會發現瀏覽器還是記住你的;
3、訪問一般的網頁伺服器端還是知道你是誰,且能正常訪問;
4、但是比如我們訪問淘寶時,如果要檢視我的訂單或進行支付時,此時還是需要再進行身份認證的,以確保當前使用者還是你。
二、認證和記住我
subject.isAuthenticated() 表示使用者進行了身份驗證登入的,即使用 Subject.login 進行了登入;
subject.isRemembered():表示使用者是通過記住我登入的,此時可能並不是真正的你(如你的朋友使用你的電腦,或者你的cookie 被竊取)在訪問的;
兩者二選一,即 subject.isAuthenticated()==true,則subject.isRemembered()==false;反之一樣。
三、建議
訪問一般網頁:如個人在主頁之類的,我們使用user 攔截器即可,user 攔截器只要使用者登入(isRemembered() || isAuthenticated())過即可訪問成功;
訪問特殊網頁:如我的訂單,提交訂單頁面,我們使用authc 攔截器即可,authc 攔截器會判斷使用者是否是通過Subject.login(isAuthenticated()==true)登入的,如果是才放行,否則會跳轉到登入頁面叫你重新登入。
四、實現
配置
/** * rememberMe管理器, cipherKey生成見{@code Base64Test.java} */ @Bean public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) { CookieRememberMeManager manager = new CookieRememberMeManager(); manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA==")); manager.setCookie(rememberMeCookie); return manager; } /** * 記住密碼Cookie */ @Bean public SimpleCookie rememberMeCookie() { SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); simpleCookie.setHttpOnly(true); simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天 return simpleCookie; }
將rememberMeManager 注入到securityManager
/**
* 安全管理器securityManager
*/
@Bean
public DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager,
CacheManager cacheShiroManager,
SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(this.shiroRealm());
securityManager.setCacheManager(cacheShiroManager);
// 將rememberMeManager 注入到securityManager
securityManager.setRememberMeManager(rememberMeManager);
securityManager.setSessionManager(sessionManager);
return securityManager;
}
RememeberMe
如果要自己做RememeberMe,需要在登入之前這樣建立Token:UsernamePasswordToken(使用者名稱,密碼,是否記住我),且呼叫UsernamePasswordToken 的:token.setRememberMe(true) 方法。
Subject currentUser = ShiroKit.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());
if ("on".equals(remember)) {
token.setRememberMe(true);
} else {
token.setRememberMe(false);
}
currentUser.login(token);