Shiro筆記七:自定義Shiro Filter過濾器
shiro自帶的Filter的問題
- shiro有自帶的過濾器在DefaultFilter裏面,但是有個問題。
filterChainDefinitionMap.put("/admin/**",“roles[admin,root]”);//中括號裏面的是角色的名字
這裏面的問題是:只有當用戶屬於admin和root角色時,才能訪問這個路徑,如果只有root角色或者只有admin角色,是不能訪問的。相當於hasAllRole()
- 現在的需求是:只需要有其中一個角色就能滿足訪問。這就需要自定義Filter
自定義Filter,繼承AuthorizationFilter,重寫裏面的isAccessAllowed方法。
public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
public CustomRolesOrAuthorizationFilter(){
}
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = this.getSubject(request, response);
//獲取當前訪問路徑所需要的角色集合
String[] rolesArray = (String[])((String[])mappedValue);
if (rolesArray != null && rolesArray.length != 0) {
Set<String> roles = CollectionUtils.asSet(rolesArray);
//當前subject是roles中的任意一個,則有權訪問。
for(String role:roles){
if(subject.hasRole(role)){
return true;
}
}
return false;
} else {
return true;
}
}
}
- 修改調用的過濾器鏈
filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");//中括號裏面的是角色的名字。
使用Redis整合CacheManager
- 使用redis原因
授權的時候每次都去查詢數據庫,對於頻繁訪問接口,性能和響應速度比較慢,使用緩存代替之。
- 解決方案:
一是:在業務代碼查詢數據庫的時候,添加進程緩存。
二是:使用Redis緩存。
- 使用Redis緩存步驟:
1、添加依賴,shiro+redis的緩存插件
<!-- shiro+redis緩存插件 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
- 編寫redis配置類
/**
* 配置RedisManager
* @return
*/
public RedisManager getRedisManager(){
RedisManager redisManager=new RedisManager();
redisManager.setHost("localhost");
redisManager.setPort(6379);
redisManager.setDatabase(1);
return redisManager;
}
- 將Redis配置整合到Shiro的CacheManager
/**
* 配置CacheManager的具體實現類
* @return
*/
public RedisCacheManager cacheManager(){//RedisCacheManager實現了CacheManager的接口
RedisCacheManager redisCacheManager=new RedisCacheManager();
redisCacheManager.setRedisManager(getRedisManager());
//設置過期時間20s
redisCacheManager.setExpire(20);
return redisCacheManager;
}
4、讓整合redis的cacheManager作爲shiro的緩存方案。在SecurityManager裏面配置
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setSessionManager(sessionManager());
//使用自定義的cacheManager
securityManager.setCacheManager(cacheManager());//此處添加緩存配置。
//推薦放到最後,不然某些版本不生效
securityManager.setRealm(customRealm());
return securityManager;
}
使用Redis整合SessionManager
- 爲什麼要對Session持久化
重啓應用,用戶無感知,可以繼續以原先的狀態繼續訪問。
- 持久化
1、使用Redis持久化,結合Shiro的RedisSessionDAO進行持久化
2、使用RedisSessionDAO加載Redis組件。
3、使用SessionManager加載RedisSessionDao。
4、注意實體類要進行序列化
/**
* 自定義redis持久化
* @return
*/
public RedisSessionDAO redisSessionDAO(){
RedisSessionDAO redisSessionDAO=new RedisSessionDAO();
redisSessionDAO.setRedisManager(getRedisManager());
redisSessionDAO.setExpire(20);
return redisSessionDAO;
}
SessionManager加載RedisSessionDao
/**
* 設置會話,自定義Session
* @return
*/
@Bean
public SessionManager sessionManager(){
CustomSessionManager customSessionManager=new CustomSessionManager();
//設置會話超時時間,單位是毫秒,默認是30分鐘
//customSessionManager.setGlobalSessionTimeout(200000);
//配置session持久化
customSessionManager.setSessionDAO(redisSessionDAO());
return customSessionManager;
}
ShiroConfig中常用Bean類配置
- LifecycleBeanPostProcessor
作用:管理shiro一些bean的生命週期 即bean初始化 與銷燬,注意管理的只是Shiro的Bean.
/**
* 作用:管理shiro一些bean的生命週期 即bean初始化 與銷燬
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
- AuthorizationAttributeSourceAdvisor
作用:加入註解的使用,不加入這個AOP註解不生效(shiro的註解 例如 @RequiresGuest)
/**
* 作用:加入註解的使用,不加入這個AOP註解不生效(shiro的註解 例如 @RequiresGuest)
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
- DefaultAdvisorAutoProxyCreator
作用: 用來掃描上下文尋找所有的Advistor(通知器), 將符合條件的Advisor應用到切入點的Bean中,需
要在LifecycleBeanPostProcessor創建後纔可以創建
/**
* 作用: 用來掃描上下文尋找所有的Advistor(通知器), 將符合條件的Advisor應用到切入點的Bean中,需
* 要在LifecycleBeanPostProcessor創建後纔可以創建
* @return
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
}