使用SpringSecurity設置角色和權(quán)限的注意點
SpringSecurity設置角色和權(quán)限
概念
在UserDetailsService的loadUserByUsername方法里去構(gòu)建當前登陸的用戶時,你可以選擇兩種授權(quán)方法,即角色授權(quán)和權(quán)限授權(quán),對應使用的代碼是hasRole和hasAuthority,而這兩種方式在設置時也有不同,下面介紹一下:
- 角色授權(quán):授權(quán)代碼需要加ROLE_前綴,controller上使用時不要加前綴
- 權(quán)限授權(quán):設置和使用時,名稱保持一至即可
使用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"));//設置權(quán)限和角色
? ? // 1. commaSeparatedStringToAuthorityList放入角色時需要加前綴ROLE_,而在controller使用時不需要加ROLE_前綴
? ? // 2. 放入的是權(quán)限時,不能加ROLE_前綴,hasAuthority與放入的權(quán)限名稱對應即可
? ? 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ū)別,但我認為,這是spring設計者的考慮,兩種性質(zhì)完成獨立的東西,不存在任何關(guān)系,一個是用做角色控制,一個是操作權(quán)限的控制,二者也并不矛盾。
Security角色和權(quán)限的概念
Security中一些可選的表達式
permitAll永遠返回truedenyAll永遠返回falseanonymous當前用戶是anonymous時返回truerememberMe當前用戶是rememberMe用戶時返回trueauthenticated當前用戶不是anonymous時返回truefullAuthenticated當前用戶既不是anonymous也不是rememberMe用戶時返回truehasRole(role)用戶擁有指定的角色權(quán)限時返回truehasAnyRole([role1,role2])用戶擁有任意一個指定的角色權(quán)限時返回truehasAuthority(authority)用戶擁有指定的權(quán)限時返回truehasAnyAuthority([authority1,authority2])用戶擁有任意一個指定的權(quán)限時返回truehasIpAddress('192.168.1.0')請求發(fā)送的Ip匹配時返回true
看到上述的表達式,應該能發(fā)現(xiàn)一些問題,在Security中,似乎并沒有嚴格區(qū)分角色和權(quán)限,
如果沒有角色和權(quán)限的區(qū)別,只需要hasRole()函數(shù)就夠了, hasAuthority()是做什么用的?
答:區(qū)別就是,hasRole()的權(quán)限名稱需要用 "ROLE_" 開頭,而hasAuthority()不需要,而且,這就是全部的區(qū)別。
在通常的系統(tǒng)設計中,我們區(qū)分角色和權(quán)限,但是,判斷 “用戶是不是管理員”,和判斷 “是否擁有管理員權(quán)限”,在代碼邏輯上,其實是完全一致的,角色是一種權(quán)限的象征,可以看做是權(quán)限的一種。因此,不區(qū)分角色和權(quán)限,本身就是合理的做法。
如果撇開別的問題不談,只考慮權(quán)限的問題,我們可以將角色視為權(quán)限的一種,但是,角色是用戶的固有屬性,在用戶管理上還是非常有必要的,在Security4中,處理“角色”(如RoleVoter、hasRole表達式等)的代碼總是會添加ROLE_前綴,它更加方便開發(fā)者從兩個不同的維度去設計權(quán)限。
Spring Security3 到 Spring Security4 的遷移文檔:
S.O. (Stack Overflow)網(wǎng)站對這個問題的描述:
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.
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
快速解決 MyBatis-Plus 中 ID 自增問題(推薦)
本文介紹了MyBatis-Plus中自動生成ID過長導致的問題及解決方法,結(jié)合示例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧2025-02-02
詳解Spring Boot的GenericApplicationContext使用教程
這篇教程展示了如何在Spring應用程序中使用GenericApplicationContext 。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
Springboot2.x+ShardingSphere實現(xiàn)分庫分表的示例代碼
這篇文章主要介紹了Springboot2.x+ShardingSphere實現(xiàn)分庫分表的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-10-10
關(guān)于Java三大特性之多態(tài)的總結(jié)
這篇文章主要介紹了關(guān)于Java三大特性之多態(tài)的總結(jié),內(nèi)容詳細,涉及多態(tài)的定義,存在條件,好處,分類及實現(xiàn)方式等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。2017-11-11
Java List的remove()方法陷阱以及性能優(yōu)化
Java List在進行remove()方法是通常容易踩坑,本文就詳細的介紹一下陷阱以及性能優(yōu)化,感興趣的可以了解一下2021-10-10

