You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rest Assured中Refresh Token并发旧令牌问题及请求实现咨询

解决Rest Assured并发场景下令牌过期及Refresh Token使用问题

一、并发场景下令牌一致性问题的解决方法

1. 加锁控制令牌生命周期

把令牌的获取、有效期检查、刷新逻辑封装到一个加锁的方法里,确保同一时间只有一个线程能执行令牌更新操作,从根源避免多个线程同时使用旧令牌或重复刷新的问题。示例代码:

private static String currentAccessToken;
private static long tokenExpiryTimestamp;
private static final Object tokenLock = new Object();

public String getValidAccessToken() {
    synchronized (tokenLock) {
        long now = System.currentTimeMillis();
        // 提前30秒触发刷新,避免令牌刚好在请求发送时过期
        if (currentAccessToken == null || now >= tokenExpiryTimestamp - 30000) {
            // 调用刷新接口获取新令牌
            Response refreshResponse = RestAssured.given()
                    .contentType(ContentType.JSON)
                    .body("{\"refreshToken\": \"" + getStoredRefreshToken() + "\"}")
                    .post("/api/token/refresh");
            
            currentAccessToken = refreshResponse.jsonPath().getString("accessToken");
            // 计算新令牌的过期时间(假设接口不返回过期时间,用固定15分钟)
            tokenExpiryTimestamp = now + 15 * 60 * 1000;
        }
        return currentAccessToken;
    }
}

2. 集成Rest Assured全局过滤器

自定义一个请求过滤器,在每个请求发送前自动检查令牌有效性,过期则刷新并注入新令牌。过滤器内部同样要保证线程安全:

public class TokenAuthFilter implements Filter {
    private String currentToken;
    private long expiryTime;
    private final Object lock = new Object();

    @Override
    public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, FilterContext ctx) {
        synchronized (lock) {
            if (currentToken == null || System.currentTimeMillis() >= expiryTime - 30000) {
                // 执行令牌刷新
                Response refreshResp = RestAssured.given()
                        .body(Map.of("refreshToken", getStoredRefreshToken()))
                        .post("/api/auth/refresh");
                
                currentToken = refreshResp.jsonPath().getString("accessToken");
                expiryTime = System.currentTimeMillis() + 15 * 60 * 1000;
            }
        }
        // 注入令牌到请求头
        requestSpec.header("Authorization", "Bearer " + currentToken);
        return ctx.next(requestSpec, responseSpec);
    }
}

注册过滤器到Rest Assured,之后所有请求都会自动处理令牌:

RestAssured.filters(new TokenAuthFilter());

3. 避免ThreadLocal滥用(特殊场景)

如果测试场景要求每个线程使用独立的身份令牌,可以用ThreadLocal存储,但要注意线程池复用的情况,任务结束后必须清理ThreadLocal,防止内存泄漏。这种方式会增加令牌刷新次数,仅适合多身份并行测试的场景。

二、使用Refresh Token发送请求的实现

Refresh Token的请求逻辑通常是调用专门的刷新接口,携带有效的Refresh Token,获取新的Access Token(部分系统会同时返回新的Refresh Token)。

基础实现示例

// 封装Refresh Token请求方法
public String refreshAccessToken(String refreshToken) {
    Response response = RestAssured.given()
            .contentType(ContentType.JSON)
            .body(Map.of("refreshToken", refreshToken))
            .post("/api/auth/refresh");
    
    // 断言请求成功,避免无效令牌继续使用
    response.then().statusCode(200);
    
    // 提取并更新存储的Refresh Token(如果接口返回新的)
    String newRefreshToken = response.jsonPath().getString("refreshToken");
    updateStoredRefreshToken(newRefreshToken);
    
    return response.jsonPath().getString("accessToken");
}

关键注意事项

  • 确保Refresh Token的有效期长于Access Token,且妥善存储(比如静态变量、加密配置文件),避免泄露。
  • 如果Refresh Token也过期,需要触发完整登录流程重新获取令牌对。
  • 刷新操作必须加锁,防止多个线程同时使用同一个Refresh Token刷新导致旧Token被服务器失效,引发后续请求失败。

内容的提问来源于stack exchange,提问作者Carolina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:45:29