springBoot集成shiro實(shí)現(xiàn)權(quán)限刷新
一、Spring Boot 集成 Shiro 基礎(chǔ)配置
引入依賴(lài):
在 Spring Boot 項(xiàng)目的pom.xml
(如果是 Maven 項(xiàng)目)中添加 Shiro 相關(guān)依賴(lài),例如:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.1</version> </dependency>
這里的版本號(hào)可以根據(jù)實(shí)際需求進(jìn)行調(diào)整。
創(chuàng)建 Shiro 配置類(lèi):
創(chuàng)建一個(gè)配置類(lèi),比如ShiroConfig
,用于配置 Shiro 的核心組件,如安全管理器(SecurityManager)、過(guò)濾器鏈(FilterChain)等。
import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration @ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class}) public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 設(shè)置安全管理器,后續(xù)創(chuàng)建并注入 shiroFilterFactoryBean.setSecurityManager(securityManager()); // 配置過(guò)濾器鏈 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設(shè)置Realm,后續(xù)創(chuàng)建并注入 securityManager.setRealm(userRealm()); return securityManager; } @Bean public UserRealm userRealm() { return new UserRealm(); } }
在上述配置中,定義了哪些 URL 需要進(jìn)行認(rèn)證(authc
),哪些可以匿名訪(fǎng)問(wèn)(anon
),并設(shè)置了安全管理器和相關(guān)的 Realm(用于用戶(hù)認(rèn)證和授權(quán)的組件)。
二、用戶(hù)認(rèn)證與授權(quán)實(shí)現(xiàn)(基于 Shiro 的 Realm)
創(chuàng)建 Realm 類(lèi):
創(chuàng)建一個(gè)繼承自AuthorizingRealm
的類(lèi),比如UserRealm
,用于實(shí)現(xiàn)用戶(hù)的認(rèn)證和授權(quán)邏輯。
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; public class UserRealm extends AuthorizingRealm { @Override protected AuthenticationInfo doAuthentication(AuthenticationToken token) throws AuthenticationException { // 獲取用戶(hù)名和密碼等信息,這里假設(shè)從token中獲取 String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); // 實(shí)際應(yīng)用中應(yīng)該從數(shù)據(jù)庫(kù)等地方查詢(xún)用戶(hù)信息進(jìn)行驗(yàn)證 User user = userService.findByUsername(username); if (user == null) { throw new AuthenticationException("用戶(hù)不存在"); } if (!user.getPassword().equals(password)) { throw new AuthenticationException("密碼錯(cuò)誤"); } // 認(rèn)證通過(guò),返回認(rèn)證信息 return new SimpleAuthenticationInfo(user, user.getPassword(), getName()); } @Override protected AuthorizationInfo doAuthorization(AuthorizationInfo authorizationInfo) { // 獲取當(dāng)前用戶(hù) User user = (User) getSubject().getPrincipal(); // 根據(jù)用戶(hù)角色和權(quán)限信息設(shè)置授權(quán)信息 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); List<Role> roles = user.getRoles(); for (Role role : roles) { simpleAuthorizationInfo.addRole(role.getName()); List<Permission> permissions = role.getPermissions(); for (Permission permission : permissions) { simpleAuthorizationInfo.addStringPermission(permission.getName()); } } return simpleAuthorizationInfo; } }
在doAuthentication
方法中實(shí)現(xiàn)用戶(hù)認(rèn)證邏輯,通過(guò)查詢(xún)數(shù)據(jù)庫(kù)等方式驗(yàn)證用戶(hù)的用戶(hù)名和密碼是否正確。在doAuthorization
方法中根據(jù)用戶(hù)的角色和權(quán)限信息設(shè)置授權(quán)信息。
三、權(quán)限刷新機(jī)制
1. 基于緩存清理的權(quán)限刷新
當(dāng)權(quán)限發(fā)生變化時(shí)(比如管理員在后臺(tái)修改了用戶(hù)的角色或權(quán)限),可以通過(guò)清理 Shiro 相關(guān)緩存來(lái)實(shí)現(xiàn)權(quán)限的刷新。
在 Realm 中添加緩存管理:
在UserRealm
類(lèi)中,可以使用 Shiro 提供的緩存機(jī)制來(lái)緩存用戶(hù)的認(rèn)證和授權(quán)信息,以提高性能。例如:
import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.ShiroSpringBootAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroCacheManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroRedisCacheManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSessionManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSpringSessionAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfiguration; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration @ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class}) public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 設(shè)置安全管理器,后續(xù)創(chuàng)建并注入 shiroFilterFactoryBean.setSecurityManager(securityManager()); // 配置過(guò)濾器鏈 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設(shè)置Realm,后續(xù)創(chuàng)建并注入 securityManager.setRealm(userRealm()); return securityManager; } @Bean public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); // 設(shè)置緩存管理器 userRealm.setCacheManager(cacheManager()); return userRealm; } @Bean public CacheManager cacheManager() { // 這里可以根據(jù)實(shí)際情況選擇不同的緩存管理器實(shí)現(xiàn),如Ehcache、Redis等 return new MemoryCacheManager(); } }
這里設(shè)置了MemoryCacheManager
作為緩存管理器示例,實(shí)際應(yīng)用中可以根據(jù)需求選擇更合適的,如RedisCacheManager
等。
權(quán)限修改時(shí)清理緩存:
當(dāng)權(quán)限發(fā)生變化時(shí),在相關(guān)的業(yè)務(wù)邏輯代碼中(比如在修改用戶(hù)角色或權(quán)限的服務(wù)方法中),需要清理對(duì)應(yīng)的緩存。例如:
import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.ShiroSpringBootAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroCacheManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroRedisCacheManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSessionManagerAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSpringSessionAutoConfiguration; import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfiguration; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration; import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration @ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class}) public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 設(shè)置安全管理器,后續(xù)創(chuàng)建并注入 shiroFilterFactoryBean.setSecurityManager(securityManager()); // 配置過(guò)濾器鏈 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設(shè)置Realm,后續(xù)創(chuàng)建并注入 securityManager.setRealm(userRealm()); return securityManager; } @Bean public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); // 設(shè)置緩存管理器 userRealm.setCacheManager(cacheManager()); return userRealm; } @Bean public CacheManager cacheManager() { // 這里可以根據(jù)實(shí)際情況選擇不同的緩存管理器實(shí)現(xiàn),如Ehcache、Redis等 return new MemoryCacheManager(); } // 在權(quán)限修改的服務(wù)方法中 public void updateUserPermissions(User user, List<Permission> newPermissions) { // 先更新數(shù)據(jù)庫(kù)中的用戶(hù)權(quán)限信息 userService.updateUserPermissions(user, newPermissions); // 清理緩存 Cache<String, AuthorizationInfo> cache = userRealm().getCacheManager().getCache("authorizationCache"); if (cache!= null) { cache.clear(); } } }
這樣,當(dāng)調(diào)用updateUserPermissions
方法修改用戶(hù)權(quán)限后,會(huì)清理掉授權(quán)信息的緩存,下次用戶(hù)訪(fǎng)問(wèn)相關(guān)資源時(shí),Shiro 會(huì)重新進(jìn)行授權(quán)計(jì)算。
2. 主動(dòng)觸發(fā)授權(quán)更新
除了通過(guò)清理緩存來(lái)間接實(shí)現(xiàn)權(quán)限刷新外,還可以在權(quán)限發(fā)生變化時(shí)主動(dòng)觸發(fā)授權(quán)更新。
在 Realm 中添加更新授權(quán)方法:
在UserRealm
類(lèi)中添加一個(gè)方法來(lái)手動(dòng)觸發(fā)授權(quán)更新,例如:
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; public class UserRealm extends AuthorizingRealm { //... 前面的認(rèn)證和授權(quán)方法 public void updateAuthorization(User user) { PrincipalCollection principals = getSubject().getPrincipals(); if (principals!= null && principals.contains(user)) { super.doAuthorization(principals); } } }
這個(gè)方法通過(guò)獲取當(dāng)前用戶(hù)的主體信息,然后調(diào)用super.doAuthorization
來(lái)重新進(jìn)行授權(quán)計(jì)算。
在權(quán)限修改業(yè)務(wù)邏輯中調(diào)用更新授權(quán)方法:
在修改用戶(hù)權(quán)限等相關(guān)業(yè)務(wù)邏輯代碼中,調(diào)用上述updateAuthorization
方法來(lái)主動(dòng)觸發(fā)授權(quán)更新。例如:
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; public class UserService { //... 其他業(yè)務(wù)方法 public void updateUserPermissions(User user, List<Permission> newPermissions) { // 先更新數(shù)據(jù)庫(kù)中的用戶(hù)權(quán)限信息 userRepository.updateUserPermissions(user, newPermissions); // 主動(dòng)觸發(fā)授權(quán)更新 UserRealm userRealm = (UserRealm) applicationContext.getBean("userRealm"); userRealm.updateAuthorization(user); } }
通過(guò)這種方式,當(dāng)權(quán)限發(fā)生變化時(shí),可以及時(shí)、主動(dòng)地更新用戶(hù)的授權(quán)信息,確保用戶(hù)的權(quán)限訪(fǎng)問(wèn)符合最新的設(shè)置。
綜上所述,在 Spring Boot 結(jié)合 Shiro 進(jìn)行管理時(shí),通過(guò)合理配置 Shiro 的基礎(chǔ)組件以及實(shí)現(xiàn)有效的權(quán)限刷新機(jī)制,可以更好地保障系統(tǒng)的安全性和權(quán)限管理的靈活性。
到此這篇關(guān)于springBoot集成shiro實(shí)現(xiàn)權(quán)限刷新的文章就介紹到這了,更多相關(guān)springBoot shiro權(quán)限刷新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot中動(dòng)態(tài)權(quán)限實(shí)時(shí)管理的實(shí)現(xiàn)詳解
- SpringBoot整合Springsecurity實(shí)現(xiàn)數(shù)據(jù)庫(kù)登錄及權(quán)限控制功能
- Spring?Boot如何接入Security權(quán)限認(rèn)證服務(wù)
- Springboot 如何使用 SaToken 進(jìn)行登錄認(rèn)證、權(quán)限管理及路由規(guī)則接口攔截
- SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT)
- SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解
- SpringBoot實(shí)現(xiàn)權(quán)限驗(yàn)證的示例步驟
相關(guān)文章
Java?如何用二維數(shù)組創(chuàng)建空心菱形
這篇文章主要介紹了Java?如何用二維數(shù)組創(chuàng)建空心菱形,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java 使用JDBC構(gòu)建簡(jiǎn)單的數(shù)據(jù)訪(fǎng)問(wèn)層實(shí)例詳解
以下是如何使用JDBC構(gòu)建一個(gè)數(shù)據(jù)訪(fǎng)問(wèn)層,包括數(shù)據(jù)轉(zhuǎn)換(將從數(shù)據(jù)庫(kù)中查詢(xún)的數(shù)據(jù)封裝到對(duì)應(yīng)的對(duì)象中……),數(shù)據(jù)庫(kù)的建立,以及如何連接到數(shù)據(jù)庫(kù),需要的朋友可以參考下2016-11-11SpringSecurity中@PermitAll與@PreAuthorize的實(shí)現(xiàn)
@PermitAll和@PreAuthorize都是處理安全性的強(qiáng)大工具,本文主要介紹了SpringSecurity中@PermitAll與@PreAuthorize的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07