【问题标题】:Volley ignores Cookie header requestVolley 忽略 Cookie 标头请求
【发布时间】:2015-09-18 07:02:23
【问题描述】:

美好的一天!

我的应用程序使用简单的 http 客户端-服务器通信,在客户端使用 Volley 库建立。首先,我发起了一个授权请求:

public class AuthenticationRequest extends StringRequest {

    private static final String TAG = AuthenticationRequest.class.getSimpleName();

    private String login;
    private String password;

    public AuthenticationRequest(int method,
                                 String url,
                                 Response.Listener<String> listener,
                                 Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    protected Map<String, String> getParams() {
        HashMap<String, String> parameters = new HashMap<>();
        parameters.put("login", login);
        parameters.put("password", password);
        return parameters;
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        for (Map.Entry<String, String> entry : response.headers.entrySet()) {
            Log.d(TAG, entry.getKey() + " -- " + entry.getValue());
        }

        String sessionId = response.headers.get("Set-Cookie");
        return Response.success(sessionId, HttpHeaderParser.parseCacheHeaders(response));
    }
}

之后,我请求与当前用户关联的设备列表。此刻我有一个来自响应头的 cookie。身份验证请求的完整标头响应输出:

  • Cache-Control -- no-store、no-cache、must-revalidate、post-check=0、pre-check=0
  • 连接 -- 保持活动
  • 内容长度 -- 16
  • 内容类型 -- 文本/html; charset=utf-8
  • 日期 -- 格林威治标准时间 2015 年 9 月 18 日星期五 06:15:57
  • 到期 -- 1981 年 11 月 19 日星期四 08:52:00 GMT
  • Pragma -- 无缓存
  • 服务器 -- nginx
  • 设置 Cookie -- PHPSESSID=osurmkq1fmnj462c3hk76l1405;路径=/
  • X-Android-Received-Millis -- 1442553247146
  • X-Android-Sent-Millis -- 1442553247096
  • X-Powered-By -- PHP/5.3.27

在 Auth 请求的 onResponce 回调中,我将 Set-Cookie 值作为 sessionId 并启动 DeviceListRequest:

public class DeviceListRequest extends StringRequest {

    private static final String TAG = DeviceListRequest.class.getSimpleName();

    private String phpSessId;

    public DeviceListRequest(int method,
                             String url,
                             Response.Listener<String> listener,
                             Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    public void setPhpSessId(String phpSessId) {
        this.phpSessId = phpSessId;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        HashMap<String, String> headers = new HashMap<>();
        Log.d(TAG, phpSessId);
        headers.put("Cookie", phpSessId);
        return headers;
    }
}

在这里,我将 sessionId 放入设备列表请求的标头,但作为响应,我看到:{"status":false,"error":"No authorization"}

在台式电脑上的 Chrome 浏览器中,按预期接收设备列表 - 问题出在 Android 上。

拜托,你能告诉我,我的代码有什么问题吗?也许我在设置标题时错了???

发送请求程序代码:

public void authenticationRequest(String login, String password) {
        final AuthenticationRequest request = new AuthenticationRequest(Request.Method.GET,
                AUTHENTICATION_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.d(TAG, "Response: " + response);
                        phpSessId = response;
                        deviceListRequest(phpSessId);
                    }
                },
                this);

        request.setLogin(login);
        request.setPassword(password);

        requestQueue.add(request);
    }

    public void deviceListRequest(String phpSessId) {
        DeviceListRequest request = new DeviceListRequest(Request.Method.GET,
                DEVICE_LIST_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.d(TAG, "Response: " + response);
                    }
                },
                this);

        request.setPhpSessId(phpSessId);

        requestQueue.add(request);
    }

【问题讨论】:

标签: android android-volley androidhttpclient android-cookiemanager


【解决方案1】:

如果您不需要兼容 Android

CookieHandler.setDefault(new CookieManager());

希望对您有所帮助。

如果您需要更多的向后兼容性,您还需要 HttpClient 的 Cookie 管理

编辑:在后一种情况下,请按照此答案传递自定义 HttpClientStack:https://stackoverflow.com/a/21271347

【讨论】:

    【解决方案2】:

    我也遇到了 Volley 标头操作的问题。 检查 Volley 内部的 HurlStack 的源代码。

    Volley 中的标头放在 Map 中,有时(我仍然不知道为什么),Volley 会一个一个地收集相同键(在您的情况下为 Set-Cookie)的标头(首先是这个 PHPSESSION,然后它将获得您的 Set-Cookie 的此路径部分)。因为这是一张地图,所以第一个会被覆盖,而你没有得到你想要的。

    我的建议是更改 HurlStack 的源代码,以便在列表中或使用不同的键(Set-Cookie1、Set-Cookie2 ..)获取这些标头。

    还可以看看 RetroFit,它处理得非常好。唯一的问题是,使用 RetroFit 您无法取消请求。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-05-21
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2019-02-12
      相关资源
      最近更新 更多