鍍金池/ 教程/ Java/ RememberMe
綜合實(shí)例
JSP 標(biāo)簽
集成驗(yàn)證碼
在線會(huì)話管理
身份驗(yàn)證
攔截器機(jī)制
編碼/加密
INI 配置
單點(diǎn)登錄
并發(fā)登錄人數(shù)控制
OAuth2 集成
動(dòng)態(tài) URL 權(quán)限控制
Realm 及相關(guān)對(duì)象
多項(xiàng)目集中權(quán)限管理及分布式會(huì)話
授予身份及切換身份
RememberMe
會(huì)話管理
與 Spring集成
與 Web 集成
緩存機(jī)制
簡(jiǎn)介
授權(quán)
SSL
無(wú)狀態(tài) Web 應(yīng)用集成

RememberMe

Shiro 提供了記住我(RememberMe)的功能,比如訪問(wèn)如淘寶等一些網(wǎng)站時(shí),關(guān)閉了瀏覽器下次再打開時(shí)還是能記住你是誰(shuí),下次訪問(wèn)時(shí)無(wú)需再登錄即可訪問(wèn),基本流程如下:

  1. 首先在登錄頁(yè)面選中 RememberMe 然后登錄成功;如果是瀏覽器登錄,一般會(huì)把 RememberMe 的 Cookie 寫到客戶端并保存下來(lái);
  2. 關(guān)閉瀏覽器再重新打開;會(huì)發(fā)現(xiàn)瀏覽器還是記住你的;
  3. 訪問(wèn)一般的網(wǎng)頁(yè)服務(wù)器端還是知道你是誰(shuí),且能正常訪問(wèn);
  4. 但是比如我們?cè)L問(wèn)淘寶時(shí),如果要查看我的訂單或進(jìn)行支付時(shí),此時(shí)還是需要再進(jìn)行身份認(rèn)證的,以確保當(dāng)前用戶還是你。

RememberMe 配置

spring-shiro-web.xml 配置

<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="sid"/>
    <property name="httpOnly" value="true"/>
    <property name="maxAge" value="-1"/>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="rememberMe"/>
    <property name="httpOnly" value="true"/>
    <property name="maxAge" value="2592000"/><!-- 30天 -->
</bean>&nbsp;
  • sessionIdCookie:maxAge=-1 表示瀏覽器關(guān)閉時(shí)失效此 Cookie;
  • rememberMeCookie:即記住我的 Cookie,保存時(shí)長(zhǎng) 30 天;
`<!-- rememberMe管理器 -->`
<bean id="rememberMeManager" 
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
    <property name="cipherKey" value="
\#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
     <property name="cookie" ref="rememberMeCookie"/>
</bean>&nbsp;

rememberMe 管理器,cipherKey 是加密 rememberMe Cookie 的密鑰;默認(rèn) AES 算法;

`<!-- 安全管理器 -->`
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    ……
  <property name="rememberMeManager" ref="rememberMeManager"/>
</bean>&nbsp;

設(shè)置 securityManager 安全管理器的 rememberMeManager;

<bean id="formAuthenticationFilter" 
class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
    ……
    <property name="rememberMeParam" value="rememberMe"/>
</bean>&nbsp;

rememberMeParam,即 rememberMe 請(qǐng)求參數(shù)名,請(qǐng)求參數(shù)是 boolean 類型,true 表示 rememberMe。

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    ……
    <property name="filterChainDefinitions">
        <value>
            /login.jsp = authc
            /logout = logout
            /authenticated.jsp = authc
            /** = user
        </value>
    </property>
</bean>&nbsp;

“/authenticated.jsp = authc” 表示訪問(wèn)該地址用戶必須身份驗(yàn)證通過(guò)(Subject. isAuthenticated()==true);而 “/** = user” 表示訪問(wèn)該地址的用戶是身份驗(yàn)證通過(guò)或 RememberMe 登錄的都可以。

測(cè)試

  1. 訪問(wèn) http://localhost:8080/chapter13/,會(huì)跳轉(zhuǎn)到登錄頁(yè)面,登錄成功后會(huì)設(shè)置會(huì)話及 rememberMe Cookie;
  2. 關(guān)閉瀏覽器,此時(shí)會(huì)話 cookie 將失效;
  3. 然后重新打開瀏覽器訪問(wèn) http://localhost:8080/chapter13/,還是可以訪問(wèn)的;
  4. 如果此時(shí)訪問(wèn) http://localhost:8080/chapter13/authenticated.jsp,會(huì)跳轉(zhuǎn)到登錄頁(yè)面重新進(jìn)行身份驗(yàn)證。

如果要自己做 RememeberMe,需要在登錄之前這樣創(chuàng)建 Token:UsernamePasswordToken(用戶名,密碼,是否記住我),如:

Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
subject.login(token);&nbsp;

subject.isAuthenticated() 表示用戶進(jìn)行了身份驗(yàn)證登錄的,即使有 Subject.login 進(jìn)行了登錄; subject.isRemembered():表示用戶是通過(guò)記住我登錄的,此時(shí)可能并不是真正的你(如你的朋友使用你的電腦,或者你的 cookie 被竊取)在訪問(wèn)的;且兩者二選一,即 subject.isAuthenticated()==true,則 subject.isRemembered()==false;反之一樣。

另外對(duì)于過(guò)濾器,一般這樣使用:
訪問(wèn)一般網(wǎng)頁(yè),如個(gè)人在主頁(yè)之類的,我們使用 user 攔截器即可,user 攔截器只要用戶登錄 (isRemembered()==true or isAuthenticated()==true) 過(guò)即可訪問(wèn)成功;
訪問(wèn)特殊網(wǎng)頁(yè),如我的訂單,提交訂單頁(yè)面,我們使用 authc 攔截器即可,authc 攔截器會(huì)判斷用戶是否是通過(guò) Subject.login(isAuthenticated()==true)登錄的,如果是才放行,否則會(huì)跳轉(zhuǎn)到登錄頁(yè)面叫你重新登錄。

因此 RememberMe 使用過(guò)程中,需要配合相應(yīng)的攔截器來(lái)實(shí)現(xiàn)相應(yīng)的功能,用錯(cuò)了攔截器可能就不能滿足你的需求了。