簡體   English   中英

使用JWT和基於角色的授權

[英]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想法是有效的。 我們以類似的方式處理這個問題。 我們的身份驗證流程如下:

  • 用戶在URL處登錄,響應頭包含JWT令牌
  • JWT令牌有一個短暫的超時(分鍾)
  • webapp以較短的間隔執行“刷新令牌”服務,該服務檢測令牌是否有效。 如果是,則服務器重新發布包括用戶的任何更新角色的新令牌,然后由webapp存儲該令牌以包括在將來對后端的請求中。

由於“刷新”服務,如果用戶的角色發生變化,或者他們被禁止進入系統,他們將自動注意到新角色或在令牌到期時間之前被“鎖定”。

這對我們來說已經有好幾年了。 我們的用戶角色不會經常更改,如果希望立即更新其角色,他們可以隨時注銷/重新登錄。

其他潛在解決方案

但是,如果在系統中立即更新用戶的角色至關重要,那么可以在Spring中檢查每個請求上的JWT標頭,並讓它進行JWT驗證,並在每個請求上添加一個新的,刷新的JWT令牌。響應。

然后,您的客戶端可以期望從服務器返回每個響應的修訂JWT令牌,並為每個后續請求使用該修訂的JWT令牌。

這可行,但如果你有很多流量,它也會相對昂貴。

這一切都取決於您的用例。 就像我說的那樣,'刷新'服務對我們來說效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM