1. 程式人生 > >shiro基本配置

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中的。