【Shiro】shiro記住我功能
在登錄後,可以將⽤戶名存在cookie中,下次訪問時,可以先不登錄,就可以識別身份。
在確實需要身份認證時,⽐如購買,⽀付或其他⼀些重要操作時,再要求⽤戶登錄即可,⽤戶體驗好。
由於可以保持⽤戶信息,系統後臺也可以更好的監控、記錄⽤戶⾏爲,積累數據。
”記住我“ 起點在登錄時刻:Subject.login(UsernameAndPasswordToken)
⽽是否確定要“記住我”,由登錄時的token控制開關: token.setRememberMe(true);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//如果需要記住我的話,需要在token中設置
token.setRememberMe(true);//shiro默認⽀持”記住我“,只要有此設置則⾃動運作。
subject.login(token);
登錄後效果
在⻚⾯中顯示,cookie中記錄的⽤戶信息
<shiro:user> 當有記住我信息,或已登錄,則顯示標籤體內容
<shiro:principal> 獲取⽤戶信息
注意:⾸⻚的訪問路徑的過濾器 不能是 authc,只能是 user 或 anon
<!-- ⾸⻚ xx.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<body>
<h2>Hello World! </h2>
<!-- 重點在此:通過如下shiro標籤顯示 -->
<shiro:user>
歡迎您,<shiro:principal/> <a href="#">退出登錄</a>
</shiro:user>
</body>
</html>
<!-- 登錄⻚⾯ login.jsp ⾃動填充⽤戶名 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/user/login" method="post">
<!-- 重點在此:<shiro:principal/> -->
username:<input type="text" name="username" value="<shiro:principal/>"> <br>
password:<input type="password" name="password"><br>
<input type="submit" value="登錄">
</form>
</body>
</html>
如果需要做⾃定義Cookie,可以明確定義如下兩個組件:
- SimpleCookie :封裝cookie的相關屬性,定製cookie寫出邏輯( 詳⻅:addCookieHeader() )
- CookieRememberMeManager :接受SecurityManager調度,獲取⽤戶信息,加密數據,並調度SimpleCookie寫出cookie
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- shiro配置 -->
<!-- Realm -->
<bean id="myRealm" class="com.siyi.realm.MyRealm">
<property name="userService" ref="userServiceImpl"/>
<property name="roleService" ref="roleServiceImpl"/>
<property name="permissionService" ref="permissionServiceImpl"/>
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA-256"/>
<property name="storedCredentialsHexEncoded" value="false"/>
<property name="hashIterations" value="10000"/>
</bean>
</property>
</bean>
<!-- 聲明SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<!-- CookieRememberMeManager注⼊給SecurityManager,
SecurityManager在處理login時,如果login成功,則會通過rememberMeManager做"記住我",
將⽤戶名存⼊cookie
-->
<property name="rememberMeManager" ref="rememberMeManager"/>
<!-- 增加配置sessionManager -->
<property name="sessionManager" ref="sessionManager"/>
</bean>
<!-- ⽣產SpringShiroFilter
( 持有shiro的過濾相關規則,可進⾏請求的過濾校驗,校驗請求是否合法 )
-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入核心對象 -->
<property name="securityManager" ref="securityManager"/>
<!-- 未登錄,沒有權限時的跳轉路徑 -->
<property name="loginUrl" value="/user/login/page"/>
<property name="unauthorizedUrl" value="/user/perms/error"/>
<!-- 過濾器鏈 -->
<property name="filterChainDefinitions">
<value>
/user/query=authc,roles["banzhang"]
/user/insert=authc,roles["banfu"]
/user/update=authc,perms[""student:update""]
/order/insert=authc,roles["xuewei"]
/user/logout=logout
</value>
</property>
</bean>
<!-- 記住我Cookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- rememberMe是cookie值中的key,value時⽤戶名的密⽂
cookie["rememberMe":"deleteMe"] 此cookie每次登陸後都會寫出,⽤於清除之前的cookie
cookie["rememberMe":username的密⽂] 此cookie也會在登錄後寫出,⽤於記錄最新的username
(ops: 如上設計,既能保證每次登陸後重新記錄cookie,也能保證切換賬號時,記錄最新賬號)
-->
<property name="name" value="rememberMe"/>
<!-- cookie只在http請求中可⽤,那麼通過js腳本將⽆法讀取到cookie信息,有效防⽌cookie被竊取 -->
<property name="httpOnly" value="true"/>
<!-- cookie的⽣命週期,單位:秒 -->
<property name="maxAge" value="604800"/><!-- 7天 -->
</bean>
<!-- 記住我管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- 對cookie的value加密的密鑰 建議每個項⽬都不⼀樣
加密⽅式AES(對稱加密)
密鑰⽣成:【KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecretKey deskey = keygen.generateKey();
System.out.println(Base64.encodeToString(deskey.getEncoded()));】
SpEL:Spring Expression Language #{表達式} #{T(類型)...}
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('c+3hFGPjbgzGdrC+MHgoRQ==')}"/>
此配置可以省略,CookieRememberMeManager⾃動完成祕鑰⽣成
-->
<!-- 注⼊SimpleCookie -->
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<!-- 增加session管理相關配置 -->
<!-- 會話Cookie模板 默認可省-->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的 key="sid" -->
<property name="name" value="JSESSIONID"/>
<!-- 只允許http請求訪問cookie -->
<property name="httpOnly" value="true"/>
<!-- cookie過期時間,-1:存活⼀個會話 ,單位:秒 ,默認爲-1-->
<property name="maxAge" value="-1"/>
</bean>
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 默認值和配置中給出的⼀致,所bean:sessionIdCookie 可以省略 -->
<property name="sessionIdCookie" ref="sessionIdCookie"/>
<!-- session全局超時時間, 單位:毫秒 ,30分鐘 默認值爲1800000-->
<property name="globalSessionTimeout" value="1800000"/>
</bean>
</beans>