導讀:在訪問系統某個或者某類介面后進行一系列權限校驗,但在后續介面中我們想讓訪問權限一直授權下去改如何處理呢?總結本篇文章希望對從事相關作業的同學能夠有所幫助或者啟發,
權限繼承意味著網站集中某個元素的權限設定將傳遞給該元素的子元素,這樣,網站會從網站集的頂級 ("root") 網站繼承權限,庫繼承自包含庫的網站,等等,權限繼承使您能夠一次進行權限分配,并且擁有該權限應用于繼承權限的所有網站、串列、庫、檔案夾和專案,此行為可降低網站集管理員和網站所有者在安全管理上所花的復雜性和時間,
一、背景
在一次性能優化中發現,檢查堆疊質摘要資訊后,發現權限校驗介面耗時高達 1.5s 以上還不涉及任何實體資料,但是對實體資料交叉查詢較為頻繁,針對這種場景需要對資料查詢的介面做性能優化,
前后檢查完后發現實體查詢資料最大的瓶頸就是權限校驗介面,其次就是實體查詢介面,
如下面場景

在經過 1~6 請求并且完成倍訓之后,如果我們需要繼續通過⑥介面回傳的實體的某些引數繼續請求,
此時我們一幫兩種解決思路
-
在原有介面中繼續優化引數,將需要第二次請求的入參和回傳引數依次追加到同一個介面中
-
新開發一個介面繼續走權限校驗和第一個介面實作步驟一樣,
但這兩種方案都合理么?
二、生成授權碼
原理其實很簡單,如我們單點登錄認證中心頒發認證碼授權訪問各個系統一樣的到底,怎么實作呢?

? 授權碼生成規則
本文權限校驗基于 Spring-security 進行改造拓展

建議沒有閱讀過的朋友有機會可閱讀下原始碼
https://spring.io/projects/spring-security#overview
對于 AuthToken 的定義我們一般定義
-
principal 驗證主體
被驗證主體的身份,在帶有用戶名和密碼的身份驗證請求的情況下,這將是用戶名,呼叫者應為身份驗證請求填充主體,
AuthenticationManager 實作通常會回傳一個包含更豐富資訊的身份驗證作為應用程式使用的主體,許多身份驗證提供程式將創建一個 UserDetails 物件作為主體
-
credentials 驗證憑證
證明主體正確的憑據,這通常是一個密碼,但可以是與 AuthenticationManager 相關的任何內容,呼叫者應填充憑據,
-
details 回話詳情
存盤有關身份驗證請求的其他詳細資訊,這些可能是 IP 地址、證書序列號等,
-
authenticated 是否已認證
用于指示 AbstractSecurityInterceptor 是否應向 AuthenticationManager 提供身份驗證令牌,通常, AuthenticationManager (或更常見的是,其 AuthenticationProvider 之一)將在成功身份驗證后回傳一個不可變的身份驗證令牌,在這種情況下,該令牌可以安全地回傳 true 給此方法,回傳 true 將提高性能,因為不再需要為每個請求呼叫 AuthenticationManager ,
出于安全原因,這個介面的實作應該非常小心地從這個方法回傳 true ,除非它們是不可變的,或者有某種方法確保屬性自最初創建以來沒有被更改
對內容進行加密,先前提到過幾種常用的加密方式,對內容進行暴力加密解密也行,
-
微服務架構 | 微服務有哪些常用的加密方式 (一)
-
微服務架構 | 資料加密有哪些常用的加密方式(二)
但是這里要強調的是加密內容以及哪些必要引數
-
用戶 SessionID:SessionID 是必須的,頒發授權碼授權的用戶物件是誰;當然這里用 UserID 也行,但是要追加失效屬性(過期時間),
-
授權介面串列:頒發訪問授權碼時候需要明確,授權碼能訪問哪些指定介面,而不能對所有介面全部開放,
-
模塊標識:頒發訪問授權碼時候最好明確是那個模塊的業務,如何授權介面中包含模塊標識二級路徑這里就可以忽略了,
-
業務標識:這里主要是針對特定場景下的業務標識,

public class MechanismAuthTokenUtil {
private static final byte[] key = new byte[]{-122, 47, -49, -55, -14, -99, -51, -69, -2, 124, -80, 45, 27, 76, -17, 92};
private static AES aes;
private static AES getAes() {
if (aes == null) {
aes = SecureUtil.aes(key);
}
return aes;
}
private static final String separator = ";";
private static final String entitySeparator = "#";
private static final String authSeparator = "\\|";
private static final String authDelimiter = "|";
....
/**
* 生成授權碼
*/
public static String encode(String moduleKey, String primaryKey, String auth) {
return encode(
SessionUtil.getSessionId(),
moduleKey,
primaryKey,
auth);
}
/**
* 生成授權碼
*/
public static String encode(String sessionId, String moduleKey, String primaryKey, String auth) {
return getAes().encryptBase64(sessionId + separator
+ moduleKey + entitySeparator
+ primaryKey + separator
+ auth);
}
....
}
三、決議授權碼
決議授權碼就是將密文解密的程序,一幫通過對稱加密或者其他方式進行處理

/**
* 決議授權碼
*
* @param token 授權碼
* @return MechanismAuth
*/
public static MechanismAuth decode(String token) {
try {
return getMechanismAuth(token, getAes().decryptStr(token));
} catch (Exception e) {
log.error("token(" + token + ")AES解密失敗", e);
return null;
}
}
private static MechanismAuth getMechanismAuth(String token, String decryptStr) {
try {
final String[] split = decryptStr.split(separator);
final String[] entitySplit = split[1].split(entitySeparator);
return new MechanismAuth(split[0], entitySplit[0], entitySplit[1], split[2]);
} catch (Exception e) {
log.error("token(" + token + ")格式不正確", e);
return null;
}
}
得到 AuthToken 定義內容
-
principal 驗證主體
-
credentials 驗證憑證
-
details 回話詳情
-
authenticated 是否已認證
得到 AuthToken 在確定授權資訊基本定義、明文組成規則、加密方式、解密方式后,還有知道系統在什么時候攔截較為合適,
四、授權攔截
對于 Web 服務攔截,如果基于 Spring-security 進行改造拓展,OncePerRequestFilter 那就是常駐貴賓了,先前在針對服務認證的時候有也有提及到過,
-
Spring Cloud中如何保證各個微服務之間呼叫的安全性?

就不做過多說明實作攔截方法

? 官方注釋上解釋
OncePerRequestFilter 過濾器基類,旨在保證在任何 servlet 容器上每個請求分派一次執行,它提供了一個帶有 HttpServletRequest 和 HttpServletResponse 引數的 doFilterInternal 方法,
從 Servlet 3.0 開始,過濾器可以作為發生在單獨執行緒中的 REQUEST 或 ASYNC 調度的一部分被呼叫,可以在 web.xml 中配置過濾器是否應該參與異步調度,但是,在某些情況下,servlet 容器會采用不同的默認配置,因此,子類可以覆寫方法 shouldNotFilterAsyncDispatch()以靜態宣告它們是否確實應該在兩種型別的調度期間被呼叫一次,以便提供執行緒初始化、日志記錄、安全性等,這種機制補充而不是取代在 web.xml 使用調度程式型別配置過濾器的需要,
子類可以使用 isAsyncDispatch(HttpServletRequest)來確定過濾器何時作為異步調度的一部分被呼叫,并使用 isAsyncStarted(HttpServletRequest)來確定請求何時處于異步模式,因此當前調度不會是最后一個對于給定的請求,
另一種也出現在它自己的執行緒中的調度型別是 ERROR ,如果子類希望靜態宣告是否應該在錯誤調度期間呼叫一次,它們可以覆寫 shouldNotFilterErrorDispatch() ,
getAlreadyFilteredAttributeName 方法確定如何識別請求已被過濾,默認實作基于具體過濾器實體的配置名稱

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/404109.html
標籤:其他
上一篇:告別繁瑣的簽到,使用 dailycheckin 就可以解決
下一篇:Vue專案打包以及部署
