Spring Security 實現使用者授權

2021-09-12 12:58:55 字數 4266 閱讀 3315

上一次,使用spring securityangular實現了使用者認證。spring security and angular 實現使用者認證

本次,我們通過spring security的授權機制,實現使用者授權。

實現十分簡單,大家認真聽,都能聽得懂。

前台實現了選單的許可權控制,但後台介面還沒進行保護,只要使用者登入成功,什麼介面都可以呼叫。

我們希望實現:使用者有什麼選單的許可權,只能訪問後台對應該選單的介面。

比如,使用者有計算機組管理的選單,就可以訪問計算機組相關的增刪改查介面,但是其他的介面都不允許訪問。

依據spring security的設計,使用者對應角色,角色對應後台介面。這是沒什麼問題的。

示例

某介面新增@secured註解,內部新增許可權表示式。

@secured("role_admin")

public listgetall()

然後再為使用者建立spring security中的角色。

這裡我們為使用者新增role_admin的角色授權,與getall方法上的@secured("role_admin")註解中的引數一致,表示該使用者有許可權訪問該方法,這就是授權。

private userdetails createuser(user user)
作為一款優秀的安全框架而言,spring security這樣設計是沒有任何問題的,我們只需要簡簡單單的幾行**就能實現介面的授權管理。

但是卻不符合我們的要求。

我們要求,在我們的系統中,使用者對應多角色。

但是我們的角色是要求可以進行動態配置的,今天有乙個系統管理員的角色,明天可能又加乙個教師的角色。

在使用者授權這方面,是可以實現動態配置的,因為使用者的許可權列表是乙個list,我可以從資料庫查當前使用者的角色,然後add進去。

private userdetails createuser(user user)
但是在介面級別,就無法實現動態配置了。大家想想,註解裡,要求的引數必須是常量,就是我們想動態配置,也實現不了啊?

@secured("role_admin")

public listgetall()

所以,我們總結,因為註解配置的限制,所以在spring security中角色是靜態的。

我們的角色是動態的,而spring security中的角色是靜態的,所以不能將我們的角色直接對映到spring security中的角色,要對映也得拿乙個我們系統中靜態的物件與之對應。

角色是動態的,這個不行了。但是我們的選單是靜態的啊。

功能模組是我們開發的,選單就這麼固定的幾個,使用者管理、角色管理、系統設定啥的,在我們開發期間就已經固定下來了,我們是不是可以使用選單結合spring security進行授權呢?

認真看這張圖,看懂了這張圖,你應該就明白了我的設計思想。

角色是動態的,我不用它授權,我使用靜態的選單進行授權。

靜態的選單對應spring security中靜態的角色,角色再對應後台介面,如此設計,就實現了我們的設想:使用者擁有哪個選單的許可權,就只擁有被該選單呼叫的相應介面許可權。

設計好了,一起來寫**吧。

spring security中有多種授權註解,個人經過對比之後選擇@secured註解,因為我覺得這個註解配置項更容易被人理解。

public @inte***ce secured
直接寫乙個角色的字串陣列傳進去即可。

@secured("role_admin")                      // 需要擁有`role_admin`角色才可訪問

@secured() // 使用者擁有`role_admin`、`role_teacher`二者之一即可訪問

注意:這裡的字串一定是以role_開頭,spring security才把它當成角色的配置,否則無效。預設的spring security是不進行授權註解攔截的,新增註解@enableglobalmethodsecurity以啟用@secured註解的全域性方法攔截。

@enableglobalmethodsecurity(securedenabled = true)         // 啟用全域性方法安全,採用@secured方式
在選單中新建乙個字段securityrolename來宣告我們的系統選單對應著哪個spring security角色。

// 該選單在spring security環境下的角色名稱

@column(nullable = false)

private string securityrolename;

建乙個類,用於存放所有spring security角色的配置資訊,供全域性呼叫。

這裡不能用列舉,@secured註解中要求必須是string陣列,如果是列舉,需要通過yunzhisecurityroleenum.role_main.name()格式獲取字串資訊,但很遺憾,註解中要求必須是常量。

還記得上次自定義http狀態碼的時候,吃了列舉類無法擴充套件的虧,以後再也不用列舉了。就算用列舉,也會設計乙個介面,列舉實現該介面,不用列舉宣告方法的引數型別,而使用介面宣告,方便擴充套件。

package club.yunzhi.huasoft.security;

/** * @author zhangxishuo on 2019-03-02

* yunzhi security 角色

* 該角色對應選單

*/public class yunzhisecurityrole

示例@secured()

public listgetall()

**體現授權思路:遍歷當前使用者的選單,根據選單中對應的security角色名進行授權。

private userdetails createuser(user user) 

logger.debug("構建使用者");

return new org.springframework.security.core.userdetails.user(user.getusername(), user.getpassword(), authorities);

}

注:這裡遇到了hibernate惰性載入引起的錯誤,啟用事務防止hibernate關閉session,深層原理目前還在研究。單元測試很簡單,供寫相同功能的人參考。

@test

public void authtest() throws exception

private string loginwithusernameandpassword(string username, string password) throws exception

感謝開源社群,感謝spring security

五行**(不算注釋),乙個註解。就解決了一直以來困擾我們的許可權問題。

初步理解Spring Security並實踐

spring security如何使用,先在你的專案pom.xml檔案中宣告依賴。org.springframework.bootgroupid spring boot starter securityartifactid dependency 然後建立乙個類並繼承websecurityconfig...

初步理解Spring Security並實踐

spring security如何使用,先在你的專案pom.xml檔案中宣告依賴。org.springframework.boot spring boot starter security 然後建立乙個類並繼承websecurityconfigureradapter這個方法,並在之類中重寫confi...

初步理解Spring Security並實踐

spring security如何使用,先在你的專案pom.xml檔案中宣告依賴。org.springframework.boot spring boot starter security 然後建立乙個類並繼承websecurityconfigureradapter這個方法,並在之類中重寫confi...