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

OkHttp 4.9.0登录后Cookie未在后续请求中加载的问题

OkHttp 4.9.0中登录Cookie未在后续请求携带导致401问题排查

我使用OkHttp 4.9.0开发SonarApi相关功能,登录请求成功后,服务器返回了XSRF-TOKEN和JWT-SESSION的Set-Cookie响应头,但后续调用updateRuleMarkdownNote接口的请求未携带这些Cookie,导致返回401未授权状态码。相关代码及请求日志如下:

相关代码

private OkHttpClient http;

public SonarApi(String serverUrl, String secret) {
    HttpLoggingInterceptor it = new HttpLoggingInterceptor();
    it.setLevel(Level.BODY);
    CookieManager cookieManager = new CookieManager();
    cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
    JavaNetCookieJar cookieJar = new JavaNetCookieJar(cookieManager);
    http = new OkHttpClient.Builder().addInterceptor(it).cookieJar(cookieJar).build();
}

public void login(String userName, String password) throws IOException {
    RequestBody formBody = new FormBody.Builder().add("login", userName).add("password", password).build();
    Request req = new Request.Builder()
            .addHeader("Accept", "application/json")
            .addHeader("Host", "x.x.x.x:9876")
            .addHeader("Origin", serverUrl)
            .addHeader("Content-Type", "application/x-www-form-urlencoded")
            .url(serverUrl + "/api/authentication/login").post(formBody).build();
    http.newCall(req).execute();
}

public boolean updateRuleMarkdownNote(String ruleKey, String mdNote) throws IOException {
    RequestBody formBody = new FormBody.Builder().add("key", ruleKey).add("markdown_note", mdNote).build();
    Request req = new Request.Builder().addHeader("Content-Type", "application/x-www-form-urlencoded").url(serverUrl + "/api/rules/update").post(formBody).build();
    int code = http.newCall(req).execute().code();
    return code >= 200 && code < 300;
}

public static void main(String[] args) {
    SonarApi sonarApi = new SonarApi("http://x.x.x.x:9876", "cac3b3c65347e87cdf1f9a7352935db79e2435f5");
    try {
        sonarApi.login("admin", "******");
        sonarApi.updateRuleMarkdownNote("custom-rules-java:ExampleRules01", "*foo*");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

请求日志

六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: --> POST http://172.25.160.238:9876/api/authentication/login
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Length: 34
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Accept: application/json
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Host: 172.25.160.238:9876
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Origin: http://172.25.160.238:9876
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Type: application/x-www-form-urlencoded
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: 
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: login=admin&password=%23Fgglgy0223
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: --> END POST (34-byte body)
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: <-- 200 http://172.25.160.238:9876/api/authentication/login (266ms)
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-Frame-Options: SAMEORIGIN
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-XSS-Protection: 1; mode=block
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-Content-Type-Options: nosniff
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Set-Cookie: XSRF-TOKEN=5iohli0jdhtla6tk8a87598log; Max-Age=259200; Expires=Mon, 19-Jun-2023 06:44:23 GMT; Path=/
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Set-Cookie: JWT-SESSION=eyJhbGciOiJIUzI1NiJ9.eyJsYXN0UmVmcmVzaFRpbWUiOjE2ODY4OTc4NjMyNTMsInhzcmZUb2tlbiI6IjVpb2hsaTBqZGh0bGE2dGs4YTg3NTk4bG9nIiwianRpIjoiQVlqQzhxcFNkRWtsQ2VJdXhIQ0IiLCJzdWIiOiJBWHd3MUhOY1NCN0xfa1UtMEhydyIsImlhdCI6MTY4Njg5Nzg2MywiZXhwIjoxNjg3MTU3MDYzfQ.sDbWX2_pNGIAIMjrgOBSyEnsBLc9fncz2-7XS_uyx-M; Max-Age=259200; Expires=Mon, 19-Jun-2023 06:44:23 GMT; Path=/; HttpOnly
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Length: 0
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Date: Fri, 16 Jun 2023 06:44:23 GMT
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Keep-Alive: timeout=60
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Connection: keep-alive
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: <-- END HTTP (0-byte body)
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: --> POST http://172.25.160.238:9876/api/rules/update
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Length: 58
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Type: application/x-www-form-urlencoded
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: 
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: key=custom-rules-java%3AExampleRules01&markdown_note=*foo*
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: --> END POST (58-byte body)
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: <-- 401 http://172.25.160.238:9876/api/rules/update (7ms)
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-Frame-Options: SAMEORIGIN
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-XSS-Protection: 1; mode=block
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: X-Content-Type-Options: nosniff
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Content-Length: 0
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Date: Fri, 16 Jun 2023 06:44:23 GMT
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Keep-Alive: timeout=60
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: Connection: keep-alive
六月 16, 2023 2:42:54 下午 okhttp3.internal.platform.Platform log
信息: <-- END HTTP (0-byte body)

问题原因及解决方案

问题根源

  1. 域名不匹配导致Cookie未被关联:登录请求中手动设置的Host头为x.x.x.x:9876,但实际请求的服务器地址是http://172.25.160.238:9876。Java原生CookieManager严格遵循RFC规范匹配Cookie域名,服务器返回的Cookie绑定在172.25.160.238上,手动设置的Host头让CookieManager误以为请求域名是x.x.x.x,导致Cookie无法被正确关联到后续请求的域名。
  2. JavaNetCookieJar的严格匹配逻辑:JavaNetCookieJar依赖原生CookieManager,其对Cookie的存储和携带逻辑要求域名完全匹配,一旦域名不一致,就不会在后续请求中自动携带Cookie。

解决办法

方法一:移除手动设置的Host头(最简单有效)

直接删除login方法中.addHeader("Host", "x.x.x.x:9876")这一行,让OkHttp自动根据请求URL生成正确的Host头,CookieManager就能正确识别域名并存储、携带Cookie。修改后的登录方法:

public void login(String userName, String password) throws IOException {
    RequestBody formBody = new FormBody.Builder()
            .add("login", userName)
            .add("password", password)
            .build();
    Request req = new Request.Builder()
            .addHeader("Accept", "application/json")
            .addHeader("Origin", serverUrl)
            .addHeader("Content-Type", "application/x-www-form-urlencoded")
            .url(serverUrl + "/api/authentication/login")
            .post(formBody)
            .build();
    http.newCall(req).execute();
}

方法二:替换为OkHttp内置的CookieJar实现(推荐)

使用OkHttp官方提供的PersistentCookieJar替代Java原生的CookieManager,它的域名匹配逻辑更灵活,适配OkHttp的请求流程。
首先添加Maven依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp-urlconnection</artifactId>
    <version>4.9.0</version>
</dependency>

然后修改SonarApi构造方法:

private OkHttpClient http;

public SonarApi(String serverUrl, String secret) {
    HttpLoggingInterceptor it = new HttpLoggingInterceptor();
    it.setLevel(Level.BODY);
    // 内存缓存Cookie,需持久化可自定义实现
    CookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
    http = new OkHttpClient.Builder()
            .addInterceptor(it)
            .cookieJar(cookieJar)
            .build();
}

注:桌面应用不适用SharedPrefsCookiePersistor,可仅使用SetCookieCache实现内存级Cookie存储,或自定义文件持久化逻辑。

方法三:确保Host头与URL域名一致

若必须手动设置Host头,需保证其值与请求URL的域名完全一致。比如服务器实际地址是172.25.160.238:9876,则Host头应设为172.25.160.238:9876,而非x.x.x.x:9876。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:24:52