簡體   English   中英

WebFlux:JWT 令牌驗證器

[英]WebFlux: JWT Token Authenticator

我們正在嘗試使用 JWT 來保護我們的 api。我們正在使用 webflux 進行我們的應用程序開發。我們的要求是讀取來自使用者的 JWT 令牌並從 JWT 中提取證書並進行驗證。

我們在我們的應用程序中對 TraceId 使用過濾器。我對 JWT 身份驗證的最佳方法是什么? 使用另一個過濾器? 或者我可以與現有的 TraceId 過濾器鏈接。spring 是否為 JWT 身份驗證提供任何解決方案?

這是我用於跟蹤 ID 過濾器的代碼。

@Component
@Slf4j
public class TraceIdFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        Map<String, String> headers = exchange.getRequest().getHeaders().toSingleValueMap();

        return chain.filter(exchange)
                .subscriberContext(context -> {
                    var traceId = "";
                    if (headers.containsKey("X-B3-TRACEID")) {
                        traceId = headers.get("X-B3-TRACEID");
                        MDC.put("X-B3-TraceId", traceId);
                    } else if (!exchange.getRequest().getURI().getPath().contains("/actuator")) {
                        log.warn("TRACE_ID not present in header: {}", exchange.getRequest().getURI());
                    }

                    // simple hack to provide the context with the exchange, so the whole chain can get the same trace id
                    Context contextTmp = context.put("X-B3-TraceId", traceId);
                    exchange.getAttributes().put("X-B3-TraceId", traceId);

                    return contextTmp;
                });

    }


} 

在 Java 項目中使用 JWT 時,建議使用此依賴項:

// https://mvnrepository.com/artifact/com.auth0/java-jwt
compile group: 'com.auth0', name: 'java-jwt', version: '3.11.0'

我個人使用implementation而不是compile並且傾向於使用“+”作為版本。

由於您使用的是 RSA,因此您需要在您使用的代碼附近建立一個這樣的變量,最好是在代碼片段的TraceIdFilter類中。

RSAPublicKey publicKey;

假設您能夠將公鑰的內容放入一個名為publicKeyStr的字符串中,您需要像這樣初始化您的公鑰對象:

try {
    X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
    publicKey = (RSAPublicKey)KeyFactory.getInstance("RSA").generatePublic(pubKeySpec);
} catch (InvalidKeySpecException | NoSuchAlgorithmException e)
{
    // Handle Exception accordingly
}

在您的過濾器代碼中,您可以像這樣瀏覽 JWT 內容(使用令牌作為保存 JWT 令牌的字符串:

DecodedJWT decodedJwt = null;
        try
        {           
            decodedJwt = JWT.require(Algorithm.RSA512(publicKey,null))
                    .build()
                    .verify(token);
        }
        catch(JWTVerificationException e)
        {
            // If your key is valid, then the token is invalid, so handle accordingly
        }

請注意,JWT 令牌有時可以包含諸如iatexp 之類的字段,這兩個字段都包含日期,如果當前時間在exp之后或iat之前,則驗證將失敗。

如果它成功並且您有一個有效的DecodedJWT對象,那么您可以查看令牌中可用的各種功能。

例如,如果您正在尋找“有效”聲明並希望它是布爾類型,則可以像這樣訪問布爾值。

Claim idClaim = decodedJwt.getClaim("valid");
        
Boolean idBool = idClaim.asBoolean();

請記住,如果令牌中沒有此類聲明,則idClaim將為空;如果它不是布爾值(或無法轉換為 1),則idBool將為空。

這是指向更多Playload接口的鏈接, DecodedJWT擴展了該接口。 JWT Payload (此鏈接在 Firefox 中比在 Edge Chromium 中更有效)

不知道 JWT 令牌中的證書應該是什么樣子,希望您能夠使用此依賴項的Claims功能找到它。

我的大部分答案都集中在 JWT 方面,但我發現了一個Stackoverflow 問題,它可能會幫助您啟發有關查詢的 WebFilter 方面的靈感。

以下是用於代碼的一些導入:

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.RSAKeyProvider;

我的例子是hantsy/spring-reactive-jwt-sample

使用Fitler填充SecurityContextHolder將其注冊SecurityContextHolder過濾器鏈中。

暫無
暫無

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

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