如何使用Spring Security實(shí)現(xiàn)用戶-角色-資源的權(quán)限控制
在Web應(yīng)用的開發(fā)中,權(quán)限管理是必不可少的一環(huán)。繼上次分享了基于 用戶-權(quán)限-資源的權(quán)限控制后,這次我們來探討如何通過Spring Security實(shí)現(xiàn) 用戶-角色-資源的權(quán)限管理。
一、基于角色的請求控制
首先,我們需要根據(jù)不同的資源路徑設(shè)置相應(yīng)的角色要求。以下是安全配置的代碼:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // 開啟授權(quán)保護(hù) http.authorizeHttpRequests(authorize -> authorize // 所有 /user/** 路徑下的請求需要 ADMIN 角色 .requestMatchers("/user/**").hasRole("ADMIN") // 對所有請求開啟授權(quán)保護(hù) .anyRequest() // 已認(rèn)證的請求自動(dòng)被授權(quán) .authenticated()); // 其他配置省略... }
在這段代碼中,我們通過hasRole("ADMIN")
方法,指定訪問/user/**
路徑的請求需要具備ADMIN
角色。這樣,我們就實(shí)現(xiàn)了基于角色的資源訪問控制。
二、加載用戶角色信息
接下來,我們需要為用戶加載其對應(yīng)的角色信息。在Spring Security中,可以通過實(shí)現(xiàn)UserDetailsService
接口的loadUserByUsername
方法:
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(User::getUsername, username); User user = userMapper.selectOne(lambdaQueryWrapper); if (user == null) { throw new UsernameNotFoundException(username); } else { return org.springframework.security.core.userdetails.User.withUsername(user.getUsername()) .password(user.getPassword()) .disabled(!user.getEnabled()) // 設(shè)置用戶的憑據(jù)是否過期,false 表示憑據(jù)未過期 .credentialsExpired(false) // 設(shè)置賬戶是否被鎖定,false 表示賬戶未鎖定 .accountLocked(false) // 為用戶分配 ADMIN 角色 .roles("ADMIN") .build(); } }
在這個(gè)方法中,我們:
- 從數(shù)據(jù)庫中根據(jù)用戶名查詢用戶信息。
- 如果用戶存在,使用
User.withUsername()
方法構(gòu)建一個(gè)UserDetails
對象。 - 通過
.roles("ADMIN")
方法為用戶分配ADMIN
角色。
需要注意的是,Spring Security在處理角色時(shí),會自動(dòng)為角色名添加"ROLE_"
前綴。因此,"ADMIN"
角色實(shí)際上對應(yīng)權(quán)限"ROLE_ADMIN"
。
三、角色與資源的關(guān)聯(lián)
通過上述配置,我們實(shí)現(xiàn)了以下功能:
- 用戶:通過數(shù)據(jù)庫加載,包含用戶名、密碼、是否啟用等信息。
- 角色:為用戶分配特定的角色,例如
ADMIN
。 - 資源:指定哪些URL路徑需要哪些角色才能訪問。
當(dāng)用戶嘗試訪問受保護(hù)的資源時(shí),Spring Security會根據(jù)用戶的角色信息決定是否授權(quán)。
四、測試角色權(quán)限控制
以下是一些測試場景,幫助驗(yàn)證我們的權(quán)限控制是否正確。
1. 未登錄用戶訪問受保護(hù)資源
當(dāng)未登錄的用戶嘗試訪問/user/list
時(shí),會被重定向到登錄頁面,提示需要先進(jìn)行身份認(rèn)證。
2. 登錄用戶訪問受保護(hù)資源
使用具備ADMIN
角色的用戶登錄后,嘗試訪問/user/list
,應(yīng)當(dāng)能夠正常訪問。
3. 角色不足的用戶訪問受保護(hù)資源(把前面改成.roles(“USER”))
如果登錄的用戶沒有ADMIN
角色,嘗試訪問/user/list
時(shí),會收到權(quán)限不足的提示,無法訪問該資源。
五、自定義異常處理
為了提升用戶體驗(yàn),我們可以自定義異常處理器,返回統(tǒng)一的JSON格式錯(cuò)誤信息。
1. 自定義未授權(quán)處理器
public class MyAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { // 創(chuàng)建結(jié)果對象 HashMap<String, Object> result = new HashMap<>(); result.put("code", -1); result.put("message", "沒有訪問該資源的權(quán)限"); // 轉(zhuǎn)換成JSON字符串 String json = JSON.toJSONString(result); // 返回響應(yīng) response.setContentType("application/json;charset=utf-8"); response.getWriter().println(json); } }
2. 注冊自定義異常處理器
http.exceptionHandling(exception -> { // 請求未認(rèn)證的處理 exception.authenticationEntryPoint(new MyAuthenticationEntryPoint()); // 請求未授權(quán)的處理 exception.accessDeniedHandler(new MyAccessDeniedHandler()); });
通過上述配置,當(dāng)用戶沒有權(quán)限訪問某個(gè)資源時(shí),會返回自定義的JSON錯(cuò)誤信息,方便前端進(jìn)行處理。
六、總結(jié)
通過以上步驟,我們實(shí)現(xiàn)了基于用戶-角色-資源的權(quán)限控制:
- 用戶:通過
UserDetailsService
加載用戶信息,并為其分配ADMIN
角色。 - 角色:使用
.roles("ADMIN")
方法為用戶指定角色。 - 資源:通過
requestMatchers("/user/**").hasRole("ADMIN")
指定需要ADMIN
角色才能訪問的資源。
這種方式的優(yōu)勢在于:
- 管理方便:角色可以包含多個(gè)權(quán)限,簡化了權(quán)限管理的復(fù)雜度。
- 靈活性高:可以根據(jù)需要?jiǎng)討B(tài)調(diào)整用戶的角色,進(jìn)而控制其訪問權(quán)限。
在實(shí)際項(xiàng)目中,通常會有一個(gè)角色和權(quán)限的對應(yīng)關(guān)系表,角色下包含多個(gè)權(quán)限,用戶可以被分配一個(gè)或多個(gè)角色。
到此這篇關(guān)于使用Spring Security實(shí)現(xiàn)用戶-角色-資源的權(quán)限控制的文章就介紹到這了,更多相關(guān)Spring Security角色權(quán)限控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot DBUnit 單元測試(小結(jié))
這篇文章主要介紹了SpringBoot DBUnit 單元測試(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09SpringCloud超詳細(xì)講解負(fù)載均衡組件Ribbon源碼
在微服務(wù)中,對服務(wù)進(jìn)行拆分之后,必然會帶來微服務(wù)之間的通信需求,而每個(gè)微服務(wù)為了保證高可用性,又會去部署集群,那么面對一個(gè)集群微服務(wù)進(jìn)行通信的時(shí)候,如何進(jìn)行負(fù)載均衡也是必然需要考慮的問題2022-07-07使用java?-jar修改SpringBoot中application.properties的配置項(xiàng)
這篇文章主要介紹了使用java?-jar修改SpringBoot中application.properties的配置項(xiàng)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02手把手教你寫Maven的archetype項(xiàng)目腳手架
本文主要介紹了Maven的archetype項(xiàng)目腳手架,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08Spring的異常處理@ExceptionHandler注解解析
這篇文章主要介紹了Spring的異常處理@ExceptionHandler注解解析,當(dāng)一個(gè)Controller中有方法加了@ExceptionHandler之后,這個(gè)Controller其他方法中沒有捕獲的異常就會以參數(shù)的形式傳入加了@ExceptionHandler注解的那個(gè)方法中,需要的朋友可以參考下2023-12-12Java(基于Struts2) 分頁實(shí)現(xiàn)代碼
這篇文章介紹了Java(基于Struts2) 分頁實(shí)現(xiàn)代碼,有需要的朋友可以參考一下2013-10-10深入理解springboot中配置文件application.properties
本文主要介紹了springboot中配置文件application.properties,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10