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

OkHttp3测试过期Token问题:调用接口始终返回200而非401

问题分析与解决方案

核心问题

你Mock客户端Instant.now()的操作无效,大概率是因为Token的过期验证逻辑是在服务端执行的——服务端用自身系统时间判断Token是否过期,客户端本地的时间修改对服务端完全没有影响,所以接口B始终返回200。

可行解决方案(按推荐优先级排序)

1. 手动生成/篡改过期Token(最直接有效)

如果你的Token是JWT格式,可通过JWT工具修改过期时间后重新生成:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public String getExpiredToken(String originalToken, String secretKey) {
    // 解析原Token的声明信息
    Claims claims = Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(originalToken)
            .getBody();
    // 将过期时间设为1小时前
    claims.setExpiration(new Date(System.currentTimeMillis() - 3600000));
    // 重新生成签名后的过期Token
    return Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS256, secretKey)
            .compact();
}

用这个篡改后的Token调用接口B,即可触发401状态码。

2. 使用预先保存的过期Token

如果无法获取签名密钥,可提前等待一个从接口A获取的Token自然过期,将其保存下来,后续测试直接复用该Token调用接口B,无需等待。

3. 用OkHttp拦截器替换请求Token

在OkHttp请求链中插入拦截器,直接将请求头中的Token替换为过期Token:

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(chain -> {
            Request originalRequest = chain.request();
            // 替换为预先准备好的过期Token
            Request modifiedRequest = originalRequest.newBuilder()
                    .header("Authorization", "Bearer " + yourPreSavedExpiredToken)
                    .build();
            return chain.proceed(modifiedRequest);
        })
        .build();

4. 控制测试环境服务端时间(需权限)

如果有权限操作测试环境服务器,可临时将服务端系统时间调至Token过期后的时刻,测试完成后再恢复正常时间;部分服务端会提供测试用的时间偏移接口,调用接口让服务端模拟未来时间也能实现验证。

5. 修复客户端Mock逻辑(仅适用于客户端验证场景)

如果Token过期验证是在客户端拦截器中执行的,你的Mock代码存在冗余转换问题,可优化为:

public void myMethod() {
    // 直接用毫秒时间戳生成过期后的Instant,无需转字符串解析
    Clock clock = Clock.fixed(
            Instant.ofEpochMilli(timestampExpiry).plusSeconds(1),
            ZoneId.of("UTC")
    );
    Instant instant = Instant.now(clock);

    try (MockedStatic<Instant> mockedStatic = mockStatic(Instant.class)) {
        mockedStatic.when(Instant::now).thenReturn(instant);
        // 调用接口B的逻辑
        callEndpointBWithToken(yourToken);
    }
}

同时要确保客户端验证逻辑确实使用Instant.now(),而非System.currentTimeMillis()或其他时间源——如果用的是后者,需要Mock对应的方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 01:37:01