为 Spring API 客户端服务存储 JWT

Storing an JWT for a Spring API client service

我有一个服务正在调用远程 API 来获取数据。 它通过服务帐户授权,我将 JWT-Token 存储在服务中作为 class 变量的请求。

当其中一种方法获得 401 响应时,服务会尝试进行身份验证并将新的 JWT 存储在旧变量中。 我可以使服务成为具有请求范围的 Bean,但我想避免这种情况。

有人可以帮助我使 JWT class 变量线程安全吗? 例如如果 2 个请求同时尝试更新 JWT 令牌会怎样?

如果所有请求的 JWT 令牌都相同,那么您可以使用 AtomicReference。在进行远程调用之前使用 getToken() 并将值应用于请求 headers.

例如:

/**
 * Initialize it with an expired {@link OAuthToken} so we don't ever need to make a '{@code null}' check.
 */
private final AtomicReference<OAuthToken> atomicRefToken = new AtomicReference<>(OAuthToken.expiredToken());


public OAuthToken getToken() {
    if (atomicRefToken.get().isExpired()) {
        atomicRefToken.set(this.fetchToken());
    }
    return atomicRefToken.get();
}

private OAuthToken fetchToken() {
    // fetch token via some call
    return new OAuthToken(....)
}

OAuthToken class.

示例
public class OAuthToken implements Serializable {

    public static final String TOKEN_TYPE_BEARER = "bearer";


    public static final Long SPARE_SECONDS = 100L;


    private final String tokenType;
    private final String accessToken;
    private final Long expiresIn;
    private final LocalDateTime expiresAt;

    public OAuthToken(@JsonProperty("token_type") @NonNull String tokenType,
                      @JsonProperty("access_token") @NonNull String accessToken,
                      @JsonProperty("expires_in") @NonNull Long expiresIn) {
        this.tokenType = tokenType;
        this.accessToken = accessToken;
        this.expiresIn = expiresIn;
        this.expiresAt = LocalDateTime.now().plus(expiresIn - SPARE_SECONDS, ChronoUnit.SECONDS);
    }

    /**
     * Create a new instance where the token is expired.
     *
     * @return new instance
     */
    public static OAuthToken expiredToken() {
        return new OAuthToken(TOKEN_TYPE_BEARER, "expired", 0L);
    }

    public boolean isExpired() {
        return LocalDateTime.now().isAfter(expiresAt);
    }

    public String value() {
        return this.accessToken;
    }

}