前提:本專案是springboot寫的後端,使用spring security + jwt實現去實現student、company、admin三種使用者角色的認證與授權
方法1:建立全域性唯一的使用者識別符號uuid
為每個使用者生成一個全域性的UUID。
前情提要:本來設計了三張資料庫表:student、company、admin。每張表存放相應角色相應使用者的基本資訊(id,username,password,email等資訊,每種使用者資訊需要的欄位大為不同,所以設計了三張表)
具體操作:建立一個同一使用者表user,用來存放所有使用者共有資訊(username,password),這張總表有一個欄位為uuid
,是每個使用者全域性唯一的id。然後在具體的student、company、admin表中引用這個全域性id,並且存放各自特有的資訊。
方法2:在jwt中包含使用者型別
在JWT的claims中明確包含使用者型別,這樣即使id重複了,可以透過使用者型別來判斷使用者是屬於哪個表。透過修改jwt生成和解析邏輯來實現
修改jwt生成邏輯
在生成jwt時,除了使用者id外,還要包含使用者型別
backend/utils/JwtUtil.java
:
...
// 呼叫getJwtBuilder方法建立一個新的jwt
public static String createJWT(String userId,String userType) {
// 這裡應該將使用者id和使用者型別拼接成一個字串為subject
String subject = userId + ',' + userType;
JwtBuilder builder = getJwtBuilder(subject, null, getUUID()); // 構建jwt
return builder.compact(); // 返回一個壓縮過的jwt
}
...
修改解析jwt邏輯
backend/config/filter/JwtAuthenticationTokenFilter.java
...
// 擷取實際的jwt部分,處理驗證jwt
token = token.substring(7);
String userId;
String userType;
try {
Claims claims = JwtUtil.parseJWT(token); // 嘗試解析
// 解析成功後,claims.getSubject()返回的是一個字串,包含兩部分"userId,userType"
String[] = claims.getSubject().split(",");
userId = parts[0];
userType = parts[1];
} catch (Exception e) {
throw new RuntimeException(e);
}
...
接下來就要去調整資料庫查詢邏輯,將查到的user實體及其usertype提取到spring security上下文中
調整資料庫查詢邏輯
當從資料庫中查詢使用者資訊時,總是同時考慮使用者ID和使用者型別。例如,在Spring服務中,可以為每種使用者型別提供不同的查詢方法,或者建立一個更通用的查詢方法,它接受使用者ID和使用者型別作為引數。
具體措施有待更新...
前端和後端的驗證
在前端和後端都進行使用者型別的驗證,確保在執行任何使用者相關的操作時都考慮到使用者型別。例如,不應該允許一個以company身份認證的使用者ID去訪問admin特有的介面。
具體措施有待更新...