从 volley JSON Object POST 方法响应中捕获 cookie

capture cookie from volley JSON Object POST method response

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

我需要能够从 header 获取 cookie 并将其分配给一个变量,以便我可以将其传递给下一个 activity。

我看过Using cookies with Android volley library

他们都好几岁了,我无法让他们工作。我不确定是不是因为他们使用 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);

}

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

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

已编辑: 我明白这个问题。你能试试这个答案吗? 下面link解释了HttpURLConnection的cookies用法 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));

试试这个 -

            @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);
                }

输出:(URL: 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}"
  }
}

Headers

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

class 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 来说非常简单,我已经创建了一个 VolleyJsonRequestclass。如果您使用的是 testOne 方法,则不需要此 class。这个 class 是为 comfort/ease 创建的,以便在您的项目中使用通用的 class 结构。 class 封装了实际请求并提供了一个自定义接口,您可以通过该接口获取响应。它有两个特殊变量,即 object 和数组。如果 json 响应有效,其中之一将为空。哪个变量将为空取决于服务器发送的响应。