[英]Using JWT with role based authorization
我正在使用Spring Security開發Web應用程序,並且我第一次嘗試使用JSON Web Tokens進行身份驗證。 應用程序應根據用戶角色限制對某些URI的訪問。 它應該提供密碼更改選項,並使Admin
用戶能夠更改其他用戶的角色。
在我接下來的教程中 ,在每個對服務器的HTTP請求中, CustomUserDetailsService
都會命中數據庫,以加載用戶的當前詳細信息,這些信息似乎很重要:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
//...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
Long userId = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
//...
}
本教程的作者提出了另一種選擇:
請注意,您還可以在JWT聲明中編碼用戶的用戶名和角色,並通過解析來自JWT的聲明來創建UserDetails對象。
然而,這是以使得難以改變用戶角色為代價的,因為我們無法在不跟蹤它們的情況下丟棄已發行的令牌。
我研究了JWT的主題並提出了以下解決方案:
讓我們在JWT聲明中存儲用戶名和角色,並設置一個短令牌到期時間(使用exp
聲明) - 在這段時間后,例如15分鍾,我們點擊數據庫檢查用戶的詳細信息。 如果角色已更改,我們將在有效負載中生成具有新角色的新令牌。 如果密碼已更改,我們要求用戶在生成新令牌之前重新進行身份驗證。
此解決方案的一個明顯缺點是,在到期時間之后,用戶訪問權限的任何更改都是有效的。
在使用JWT時,還有其他方法可以解決處理用戶詳細信息更改的問題嗎?
我們使用帶有Spring Security和Angular webapp的JWT令牌。
我認為您Possible Solution
想法是有效的。 我們以類似的方式處理這個問題。 我們的身份驗證流程如下:
由於“刷新”服務,如果用戶的角色發生變化,或者他們被禁止進入系統,他們將自動注意到新角色或在令牌到期時間之前被“鎖定”。
這對我們來說已經有好幾年了。 我們的用戶角色不會經常更改,如果希望立即更新其角色,他們可以隨時注銷/重新登錄。
其他潛在解決方案
但是,如果在系統中立即更新用戶的角色至關重要,那么可以在Spring中檢查每個請求上的JWT標頭,並讓它進行JWT驗證,並在每個請求上添加一個新的,刷新的JWT令牌。響應。
然后,您的客戶端可以期望從服務器返回每個響應的修訂JWT令牌,並為每個后續請求使用該修訂的JWT令牌。
這可行,但如果你有很多流量,它也會相對昂貴。
這一切都取決於您的用例。 就像我說的那樣,'刷新'服務對我們來說效果很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.