shiro基本配置
shiro:web配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-shiro.xml
</param-value>
</context-param>
載入shiro配置檔案<!-- shiro filter的名字是shiroFilter,那麼在spring的配置檔案中要有一個名字為shiroFilter的bean --> <filter> <!-- 這裡的filter-name 要和spring 的applicationContext-shiro.xml 裡的 org.apache.shiro.spring.web.ShiroFilterFactoryBean 的bean name 相同 --> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>targetBeanName</param-name> <param-value>shiroFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這裡的shiroFilter對應著spring-shiro配置檔案中的shiroFilter,/*表示shiro將過濾全部路徑
spring-shiro.xml配置
<!-- wbe.xml中shirofilter對應的bean --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login.action" /> <property name="successUrl" value="/query.action" /> <!-- 制定拒絕訪問頁面 --> <property name="unauthorizedUrl" value="/error.jsp" /> <!-- 自定義filter配置 --> <property name="filters"> <map> <!-- 將自定義 的FormAuthenticationFilter注入shiroFilter中 --> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> <property name="filterChainDefinitions"> <value> <!-- 請求這個地址自動退出 --> /logout.action = logout <!-- 所有url可以匿名訪問 --> /login.jsp = anon <!-- 查詢許可權 --> <!-- /query.action = perms[user:query] /add.action = perms[user:add] /update.action = perms[user:update] --> <!-- 所有url都需要認證才可以訪問 --> /** = authc </value> </property> </bean>
securityManager:安全管理器
loginUrl這個value就是shiro所指定的登入介面,successUrl指定登入成功介面,如果不配置登入成功將預設跳轉到上次請求路徑,unauthorizedUrl這個是一個沒有許可權路徑,當沒有許可權就會到這個介面,
filters:這個是一個自定義的filter,也就是自定義的過濾方式,上面寫的是一個表單過濾器,表單過濾器一般載登入的時候使用
filterChainDefinitions:shiro過濾器鏈。這個鏈是從上向下走的基本的有login,logout,anon,authc
安全管理器securityManager
<!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"></property> <!-- 快取管理器 --> <property name="cacheManager" ref="cacheManager"></property> <!-- session會話管理器 --> <property name="sessionManager" ref="sessionManager"></property> <!-- 記住我 --> <property name="rememberMeManager" ref="rememberMeManager"></property> </bean>
realm域:realm新增到securityManager,realm相當於資料來源,從資料庫獲取資料,交給securtyManager來認證,授權
cacheManager快取管理器:每當系統需要訪問需要許可權的資源的時候,都需要securityMananger從新去獲取,這個大大降低的效率,所以可以配置快取管理器,降低資源消耗。
sessionManager會話管理器:一次登入就是一次會話,如果一個使用者一直登入賬號,而忘記退出了,這個賬戶就會一直存在(如果不關閉瀏覽器),這裡我們就需要會話管理器,可以設定生命週期。
rememberManager:從字面上理解就是記住密碼
realm
<!-- realm -->
<bean id="userRealm" class="com.my.shiro.realm.userRealm">
<!-- 將憑證匹配器設定到realm中,realm按照憑證匹配器的要求進行雜湊 -->
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
realm:需要自己寫一個類,繼承AuthorizingRealm
credentialsMatcher:認證的方式,一般資料庫存密碼不會存明文,一般都是加密的,所以認證的時候也需要加密認證,這個就是一種認證方式
package com.my.shiro.realm;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.my.shiro.Entity.User;
import com.my.shiro.Service.Impl.userServiceImpl;;
public class userRealm extends AuthorizingRealm{
@Autowired
private userServiceImpl userService;
//授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//從principals獲取主身份資訊
User user = (User) principals.getPrimaryPrincipal();
//根據身份資訊獲取許可權資訊
//模擬連結資料庫
//System.out.println("11111"+user);
List<String> permissions = new ArrayList<String>();
String permission = "";
permission = userService.findpermission(user.getUsername());
if(permission != null&&!permission.equals("")){
String a[] = permission.split(",");
for(int i = 0; i < a.length; i++){
permissions.add(a[i]);
}
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
//設定realm名稱
@Override
public void setName(String name) {
super.setName("testrealm");
}
//認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//first從token(使用者輸入)中獲取使用者資訊
String usercode = (String) token.getPrincipal();
//根據usercode從資料看中查詢
//模擬資料庫
String password = userService.findpassword(usercode);
//鹽
String salt = "aa";
User u1 = new User();
u1.setPassword(password);
u1.setUsername(usercode);
SimpleAuthenticationInfo simpleAuthenticationInfo = new
SimpleAuthenticationInfo(u1, password, ByteSource.Util.bytes(salt), this.getName());
return simpleAuthenticationInfo;
}
public void clearCached(){
PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
super.clearCache(principals);
}
}
這裡面有三個繼承父類方法,doGetAuthorizationInfo,doGetAuthenticationInfo,setName
doGetAuthorizationInfo:授權,將已經認證過的人使用者分配許可權,返回一個授權資訊
doGetAuthenticationInfo:認證,使用者登入的時候需要認證,返回一個憑證資訊
setName:realm名字
credentialsMatcher憑證匹配器
<!-- 憑證匹配器 -->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean>
hashAlgorithmName:這個使用的匹配方式就md5,就是加密之後在和資料庫資料進行比較
hashIterations:加密迭代次數,1程式碼加密迭代1次
cacheManager快取管理器
<!-- 快取管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml" />
</bean>
這裡需要載入一個配置檔案shiro-ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--diskStore:快取資料持久化的目錄 地址 -->
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
sessionManager會話管理器
<!-- 會話管理器 -->
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session的失效時長,單位毫秒 -->
<property name="globalSessionTimeout" value="600000" />
<!-- 刪除失效的session -->
<property name="deleteInvalidSessions" value="true" />
</bean>
globalSessionTimeout:session儲存時間
deleteInvalidSessions:失效的session是否刪除
formAuthenticationFilter表單過濾器
<bean id="formAuthenticationFilter" class="com.my.shiro.realm.FormAuthentication">
<!-- 表單中賬號的input名稱 -->
<property name="usernameParam" value="username" />
<!-- 表單中密碼的input名稱 -->
<property name="passwordParam" value="password" />
<!-- 記住我input的名稱 -->
<property name="rememberMeParam" value="rememberMe" />
</bean>
usernameParam,passwordParam,rememberMeParam對應的就是html表單提交input標籤的name屬性
<form action="/shiro/login.action" method="post"><br>
賬號:<input type="text" name="username"><br>
密碼:<input type="password" name="password"><br>
<input type="checkbox" name="rememberMe">自動登入<br>
<input type="submit" value="提交">
</form>
登入的時候一般會自動進行表單驗證,但是shiro提供的表單驗證不能驗證驗證碼之類的,所以需要自己實現FormAuthenticationFilter重寫onAccessDenied,在裡面可以進行驗證碼的驗證
package com.my.shiro.realm;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
public class FormAuthentication extends FormAuthenticationFilter{
//認證方法
//可以進行驗證碼校驗
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
System.out.println(111);
return super.onAccessDenied(request, response);
}
}
rememberMeManager記住我
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie"></property>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的名字 -->
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="2592000" /><!-- 30天 -->
</bean>
這裡主要配置cookie名字,和cookie存活時間,可以就密碼可以儲存多久不登陸。
shiro生命週期
<!-- 保證實現了Shiro內部lifecycle函式的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
把shrio生命週期交給spring管理shiro註解支援
<!-- 開啟aop,對類代理 -->
<aop:config proxy-target-class="true"/>
<!-- 開啟shiro註解支援 -->
<bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
由於shiro是基於aop的所以首先要開啟aop支援,在使用org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor開啟註解支援
注意這個是寫在springmvc.xml中的。