使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn)
SpringSecurity設(shè)置角色和權(quán)限
概念
在UserDetailsService的loadUserByUsername方法里去構(gòu)建當(dāng)前登陸的用戶時(shí),你可以選擇兩種授權(quán)方法,即角色授權(quán)和權(quán)限授權(quán),對(duì)應(yīng)使用的代碼是hasRole和hasAuthority,而這兩種方式在設(shè)置時(shí)也有不同,下面介紹一下:
- 角色授權(quán):授權(quán)代碼需要加ROLE_前綴,controller上使用時(shí)不要加前綴
- 權(quán)限授權(quán):設(shè)置和使用時(shí),名稱保持一至即可
使用mock代碼
@Component
public class MyUserDetailService implements UserDetailsService {
? @Autowired
? private PasswordEncoder passwordEncoder;
? @Override
? public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
? ? User user = new User(name,
? ? ? ? passwordEncoder.encode("123456"),
? ? ? ? AuthorityUtils.commaSeparatedStringToAuthorityList("read,ROLE_USER"));//設(shè)置權(quán)限和角色
? ? // 1. commaSeparatedStringToAuthorityList放入角色時(shí)需要加前綴ROLE_,而在controller使用時(shí)不需要加ROLE_前綴
? ? // 2. 放入的是權(quán)限時(shí),不能加ROLE_前綴,hasAuthority與放入的權(quán)限名稱對(duì)應(yīng)即可
? ? return user;
? }
}上面使用了兩種授權(quán)方法,大家可以參考。
在controller中為方法添加權(quán)限控制
?@GetMapping("/write")
? @PreAuthorize("hasAuthority('write')")
? public String getWrite() {
? ? return "have a write authority";
? }
? @GetMapping("/read")
? @PreAuthorize("hasAuthority('read')")
? public String readDate() {
? ? return "have a read authority";
? }
? @GetMapping("/read-or-write")
? @PreAuthorize("hasAnyAuthority('read','write')")
? public String readWriteDate() {
? ? return "have a read or write authority";
? }
? @GetMapping("/admin-role")
? @PreAuthorize("hasRole('admin')")
? public String readAdmin() {
? ? return "have a admin role";
? }
? @GetMapping("/user-role")
? @PreAuthorize("hasRole('USER')")
? public String readUser() {
? ? return "have a user role";
? }網(wǎng)上很多關(guān)于hasRole和hasAuthority的文章,很多都說二者沒有區(qū)別,但我認(rèn)為,這是spring設(shè)計(jì)者的考慮,兩種性質(zhì)完成獨(dú)立的東西,不存在任何關(guān)系,一個(gè)是用做角色控制,一個(gè)是操作權(quán)限的控制,二者也并不矛盾。
Security角色和權(quán)限的概念
Security中一些可選的表達(dá)式
permitAll永遠(yuǎn)返回truedenyAll永遠(yuǎn)返回falseanonymous當(dāng)前用戶是anonymous時(shí)返回truerememberMe當(dāng)前用戶是rememberMe用戶時(shí)返回trueauthenticated當(dāng)前用戶不是anonymous時(shí)返回truefullAuthenticated當(dāng)前用戶既不是anonymous也不是rememberMe用戶時(shí)返回truehasRole(role)用戶擁有指定的角色權(quán)限時(shí)返回truehasAnyRole([role1,role2])用戶擁有任意一個(gè)指定的角色權(quán)限時(shí)返回truehasAuthority(authority)用戶擁有指定的權(quán)限時(shí)返回truehasAnyAuthority([authority1,authority2])用戶擁有任意一個(gè)指定的權(quán)限時(shí)返回truehasIpAddress('192.168.1.0')請(qǐng)求發(fā)送的Ip匹配時(shí)返回true
看到上述的表達(dá)式,應(yīng)該能發(fā)現(xiàn)一些問題,在Security中,似乎并沒有嚴(yán)格區(qū)分角色和權(quán)限,
如果沒有角色和權(quán)限的區(qū)別,只需要hasRole()函數(shù)就夠了, hasAuthority()是做什么用的?
答:區(qū)別就是,hasRole()的權(quán)限名稱需要用 "ROLE_" 開頭,而hasAuthority()不需要,而且,這就是全部的區(qū)別。
在通常的系統(tǒng)設(shè)計(jì)中,我們區(qū)分角色和權(quán)限,但是,判斷 “用戶是不是管理員”,和判斷 “是否擁有管理員權(quán)限”,在代碼邏輯上,其實(shí)是完全一致的,角色是一種權(quán)限的象征,可以看做是權(quán)限的一種。因此,不區(qū)分角色和權(quán)限,本身就是合理的做法。
如果撇開別的問題不談,只考慮權(quán)限的問題,我們可以將角色視為權(quán)限的一種,但是,角色是用戶的固有屬性,在用戶管理上還是非常有必要的,在Security4中,處理“角色”(如RoleVoter、hasRole表達(dá)式等)的代碼總是會(huì)添加ROLE_前綴,它更加方便開發(fā)者從兩個(gè)不同的維度去設(shè)計(jì)權(quán)限。
Spring Security3 到 Spring Security4 的遷移文檔:
S.O. (Stack Overflow)網(wǎng)站對(duì)這個(gè)問題的描述:
Think of a GrantedAuthority as being a "permission" or a "right". Those "permissions" are (normally) expressed as strings (with the getAuthority() method). Those strings let you identify the permissions and let your voters decide if they grant access to something.
You can grant different GrantedAuthoritys (permissions) to users by putting them into the security context. You normally do that by implementing your own UserDetailsService that returns a UserDetails implementation that returns the needed GrantedAuthorities.
Roles (as they are used in many examples) are just "permissions" with a naming convention that says that a role is a GrantedAuthority that starts with the prefix ROLE_. There's nothing more. A role is just a GrantedAuthority - a "permission" - a "right". You see a lot of places in spring security where the role with its ROLE_ prefix is handled specially as e.g. in the RoleVoter, where the ROLE_ prefix is used as a default. This allows you to provide the role names withtout the ROLE_ prefix. Prior to Spring security 4, this special handling of "roles" has not been followed very consistently and authorities and roles were often treated the same (as you e.g. can see in the implementation of the hasAuthority() method in SecurityExpressionRoot - which simply calls hasRole()). With Spring Security 4, the treatment of roles is more consistent and code that deals with "roles" (like the RoleVoter, the hasRole expression etc.) always adds the ROLE_ prefix for you. So hasAuthority('ROLE_ADMIN') means the the same as hasRole('ADMIN') because the ROLE_ prefix gets added automatically. See the spring security 3 to 4 migration guide for futher information.
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用MDC快速查詢應(yīng)用接口全部執(zhí)行日志
這篇文章主要為大家介紹了使用MDC快速查詢應(yīng)用接口全部執(zhí)行日志的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
快速解決 MyBatis-Plus 中 ID 自增問題(推薦)
本文介紹了MyBatis-Plus中自動(dòng)生成ID過長(zhǎng)導(dǎo)致的問題及解決方法,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-02-02
Java設(shè)計(jì)模式之代理模式與裝飾模式實(shí)例詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之代理模式與裝飾模式,結(jié)合具體實(shí)例形式分析了代理模式與裝飾模式的概念、功能、java實(shí)現(xiàn)方法與相關(guān)使用注意事項(xiàng),需要的朋友可以參考下2017-09-09
詳解Spring Boot的GenericApplicationContext使用教程
這篇教程展示了如何在Spring應(yīng)用程序中使用GenericApplicationContext 。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
Springboot2.x+ShardingSphere實(shí)現(xiàn)分庫分表的示例代碼
這篇文章主要介紹了Springboot2.x+ShardingSphere實(shí)現(xiàn)分庫分表的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Java四種權(quán)限修飾符知識(shí)點(diǎn)詳解
在本篇文章里小編給大家分享的是關(guān)于Java四種權(quán)限修飾符知識(shí)點(diǎn)詳解內(nèi)容,需要的朋友們可以參考下。2020-05-05
關(guān)于Java三大特性之多態(tài)的總結(jié)
這篇文章主要介紹了關(guān)于Java三大特性之多態(tài)的總結(jié),內(nèi)容詳細(xì),涉及多態(tài)的定義,存在條件,好處,分類及實(shí)現(xiàn)方式等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
Java List的remove()方法陷阱以及性能優(yōu)化
Java List在進(jìn)行remove()方法是通常容易踩坑,本文就詳細(xì)的介紹一下陷阱以及性能優(yōu)化,感興趣的可以了解一下2021-10-10

