【问题标题】:capture cookie from volley JSON Object POST method response从凌空 JSON 对象 POST 方法响应中捕获 cookie
【发布时间】:2019-07-10 20:37:04
【问题描述】:

我正在使用 android 上的 volley 库发送 POST 请求。一旦我得到 json 响应,服务器就会在标头中发回一个 cookie。当我使用 android studio 中的分析器检查网络流量时,我可以看到 cookie。

我需要能够从标头中获取 cookie 并将其分配给一个变量,以便我可以将它传递给下一个活动。

我看过Using cookies with Android volley libraryhow to get cookies from volley response

他们都几岁了,我无法让他们工作。我不确定是不是因为他们使用 GET 请求而我的是 POST 请求。

有没有一种简单的方法可以从服务器响应中获取 cookie?

这是我目前的代码,一切都很好,除了抓取cookie。

 JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, cartUrl, jsonParams,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    //Obviously this will not work becuase .getCookie() requires a url as a parameter
                    //There must be a method something like this to capture the response and get the cookie.
                    String chocolateChip = CookieManager.getInstance().getCookie(response);

                    startActivity(postIntent);

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });

    postRequestQue.add(postRequest);

}

【问题讨论】:

  • 请分享您正在使用的 API 和 Android 操作系统版本
  • @codeKracken 我已经提交了我的答案。请检查

标签: java android json cookies android-volley


【解决方案1】:

输出:(网址:https://www.secureserver.net/api/v1/cart/508688?redirect=false

注意:请尝试使用 privateLabelId,因为以下输出是 HTTP 400 请求的结果

{
  "error": {
    "statusCode": 400,
    "name": "invalid-product",
    "message": "Bad Request. Invalid {productId} in {items}"
  }
}

标题

com.example.test E/MainActivity: Name Access-Control-Allow-Credentials Value true
com.example.test E/MainActivity: Name Cache-Control Value max-age=0, no-cache, no-store
com.example.test E/MainActivity: Name Connection Value close
com.example.test E/MainActivity: Name Content-Length Value 109
com.example.test E/MainActivity: Name Content-Type Value application/json; charset=utf-8
com.example.test E/MainActivity: Name Date Value Thu, 21 Feb 2019 06:09:34 GMT
com.example.test E/MainActivity: Name Expires Value Thu, 21 Feb 2019 06:09:34 GMT
com.example.test E/MainActivity: Name P3P Value CP="IDC DSP COR LAW CUR ADM DEV TAI PSA PSD IVA IVD HIS OUR SAM PUB LEG UNI COM NAV STA"
com.example.test E/MainActivity: Name Pragma Value no-cache
com.example.test E/MainActivity: Name Server Value nginx
com.example.test E/MainActivity: Name Vary Value Origin, Accept-Encoding
com.example.test E/MainActivity: Name X-Android-Received-Millis Value 1550729374476
com.example.test E/MainActivity: Name X-Android-Response-Source Value NETWORK 400
com.example.test E/MainActivity: Name X-Android-Selected-Protocol Value http/1.1
com.example.test E/MainActivity: Name X-Android-Sent-Millis Value 1550729373659
com.example.test E/MainActivity: Name X-ARC Value 102
com.example.test E/MainActivity: Name X-Content-Type-Options Value nosniff
com.example.test E/MainActivity: Name X-Download-Options Value noopen
com.example.test E/MainActivity: Name X-Frame-Options Value DENY
com.example.test E/MainActivity: Name X-XSS-Protection Value 1; mode=block

类 VolleyJsonRequest

import android.util.Log;
import android.support.annotation.Nullable;

import com.android.volley.Header;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

class VolleyJsonRequest {
    private ResponseListener listener;
    private int method;
    private String url;
    private List<Header> headers = new ArrayList<>();
    private JSONObject body;
    private int statusCode;

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

    public VolleyJsonRequest(int method, String url, JSONObject body, ResponseListener listener) {
        this.listener = listener;
        this.method = method;
        this.url = url;
        this.body = body;

    }

    public Request get() {
        return new Request(method, url, body.toString(), responseListener, errorListener);
    }

    Response.Listener<String> responseListener = new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            deliverResult(response);
        }
    };

    Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            statusCode = error.networkResponse.statusCode;
            headers.addAll(error.networkResponse.allHeaders);
            String json;
            try {
                json = new String(
                        error.networkResponse.data,
                        HttpHeaderParser.parseCharset(error.networkResponse.headers));
                deliverResult(json);
            } catch (
                    UnsupportedEncodingException e) {
                Log.e(TAG, Log.getStackTraceString(e));
            }
        }
    };


    private void deliverResult(String response) {
        try {
            Object object = new JSONTokener(response).nextValue();
            if (object instanceof JSONObject) {
                listener.onResponse(statusCode, headers, (JSONObject) object, null);
            } else {
                listener.onResponse(statusCode, headers, null, (JSONArray) object);
            }
        } catch (JSONException e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }


    class Request extends JsonRequest {

        public Request(int method, String url, @Nullable String requestBody, Response.Listener listener, @Nullable Response.ErrorListener errorListener) {
            super(method, url, requestBody, listener, errorListener);
        }

        @Override
        protected Response parseNetworkResponse(NetworkResponse response) {
            headers.addAll(response.allHeaders);
            statusCode = response.statusCode;
            String string;
            try {
                string = new String(
                        response.data,
                        HttpHeaderParser.parseCharset(response.headers));
            } catch (
                    UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            }

            return Response.success(
                    string,
                    HttpHeaderParser.parseCacheHeaders(response));

        }
    }

    public interface ResponseListener {
        void onResponse(int statusCode, List<Header> headers, JSONObject object, JSONArray array);
    }

}

测试

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.android.volley.Header;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.List;

public class MainActivity extends AppCompatActivity implements VolleyJsonRequest.ResponseListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private RequestQueue queue;

    String requestBody = "{\n" +
            "  \"items\": [\n" +
            "    {\n" +
            "      \"id\": \"string\",\n" +
            "      \"domain\": \"string\"\n" +
            "    }\n" +
            "  ],\n" +
            "  \"skipCrossSell\": true\n" +
            "}";
    String url = "https://www.secureserver.net/api/v1/cart/508688?redirect=false";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        queue = Volley.newRequestQueue(this);
        testOne();
        testTwo();
    }

    private void testOne(){
        JsonRequest request = new JsonRequest(Request.Method.POST, url, requestBody, new Response.Listener() {
            @Override
            public void onResponse(Object response) {
                Log.e(TAG,"Response " + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

                try {
                    String response = new String(
                            error.networkResponse.data,
                            HttpHeaderParser.parseCharset(error.networkResponse.headers));

                    Log.e(TAG,error.networkResponse.allHeaders.toString());
                    Log.e(TAG,response);

                } catch (UnsupportedEncodingException e) {
                    Log.e(TAG,e.getMessage());
                }
            }
        }) {
            @Override
            protected Response parseNetworkResponse(NetworkResponse response) {
                try {


                    List<Header> headers = response.allHeaders;
                    for(Header header: headers){
                        Log.e(TAG,"Name " + header.getName() + " Value " + header.getValue());
                    }

                    String json = new String(
                            response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    return Response.success(
                            new JSONObject(json),
                            HttpHeaderParser.parseCacheHeaders(response));
                } catch (UnsupportedEncodingException e) {
                    return Response.error(new ParseError(e));
                } catch (JSONException e) {
                    return Response.error(new ParseError(e));
                }
            }
        };

        queue.add(request);
    }

    private  void testTwo(){

        VolleyJsonRequest jsonRequest = null;
        try {
            jsonRequest = new VolleyJsonRequest(Request.Method.POST,url, new JSONObject(requestBody),this);
            queue.add(jsonRequest.get());
        } catch (JSONException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void onResponse(int statusCode, List<Header> headers, JSONObject object, JSONArray array) {


        Log.e(TAG,"-------------------------------");

        for(Header header: headers){
            Log.e(TAG,"Name " + header.getName() + " Value " + header.getValue());
        }


        if (object != null){
            // handle your json object
        }else if (array != null){
            // handle your json array
        }
    }
}

我尝试了两种方法,即 testOne 和 testTwo。两者都工作正常。 testOne 对于我创建的 testTwo 来说非常简单 VolleyJsonRequest 类。如果您使用 testOne 方法,则不需要此类。创建此类只是为了在您的项目中使用通用类结构的舒适/轻松。此类封装实际请求并提供一个自定义接口,您可以通过该接口获取响应。它有两个特殊变量,即对象和数组。在有效的 json 响应的情况下,其中之一将为 null。哪个变量将为空取决于服务器发送的响应。

【讨论】:

  • 你是老板!经过数周的试验和搜索,终于成功了。
  • 如果您有一个简单的解决方案,我确实还有一个问题。我正在尝试获取以 ShopperID 开头的 Set-Cookie 名称。现在我正在使用 String ChocolateChip = string.valueOf(headers.get(11));String trimedCookie = ChocolateChip.substring(29, ChocolateChip.length()-1);似乎应该有一个更简单的方法。
  • 我顺便用了你的 testone() 方法。再次感谢我非常感谢您提供的帮助。
  • @codeKracken,看看是否有帮助 String s = headers.get(11).getValue().split("textyouwanttoskip")[1];
  • 谢谢你,这很有帮助。我非常感谢您提供的所有帮助。
【解决方案2】:

试试这个 -

            @Override
            public String getBodyContentType() {
                return "application/json";
            }

            @Override
                protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                    // since we don't know which of the two underlying network vehicles
                    // will Volley use, we have to handle and store session cookies manually
                    Log.i("response",response.headers.toString());
                    Map<String, String> responseHeaders = response.headers;
                    String rawCookies = responseHeaders.get("Set-Cookie");
                    Log.i("cookies",rawCookies);
                    prefLogin.setSessionId(rawCookies); // save your cookies using shared prefernece
                    return super.parseNetworkResponse(response);
                }

【讨论】:

  • 感谢这即将结束,但它返回 I/cookies: currency=USD;域=secureserver.net;路径=/; Expires=Wed, 2020 年 2 月 19 日 00:24:38 GMT 并且不返回完整的 cookie,最重要的是我正在尝试捕获 cookie ShopperId508688=somerandomestringgoeshere;
  • 感谢您的建议,但 rawCookies 会在没有来自标头的实际 cookie 的情况下返回。
【解决方案3】:

您是否在同一个问题中检查了this answer?这是一个可接受的答案,并显示了从响应中捕获 cookie 并稍后通过在后续请求中添加 cookie 来发送它们所需的实现。

另外,请查看以下屏幕截图。我从this link 拿走了它。

编辑: 我明白这个问题。你能试试这个答案吗? 以下链接解释了HttpURLConnection 的 cookie 的使用 https://developer.android.com/reference/java/net/HttpURLConnection#sessions-with-cookies

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

您也可以尝试将以下参数添加到CookieManager 构造函数以接受所有cookie:

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

【讨论】:

  • 感谢您对此进行调查,但这些方法都不起作用。 AbstractHttpClient 是一个我没有或不知道如何获取的类,并且不推荐使用 HttpClientStack 。我能找到的大多数答案都是从 2013 年开始的几年或更久的时间。我似乎找不到任何最新信息。
  • 嘿@codeKracken,我已经更新了我的答案。如果这有帮助,请告诉我。
  • @Mohit Ajwani 感谢您的帮助,但是这些根本不起作用。这似乎接近 String rawCookies = responseHeaders.get("Set-Cookie");但由于某种原因没有捕获正确的 cookie。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2016-07-25
  • 1970-01-01
  • 2019-01-03
  • 1970-01-01
  • 2020-09-12
  • 2021-06-24
  • 1970-01-01
相关资源
最近更新 更多