HttpPost 上的 x-csrf-token 验证失败

x-csrf-token validation fails on HttpPost

我必须 post xml 有效负载到 ODATA 服务,该服务需要身份验证和 x-csrf-token

我有两个AsyncTasks。在第一个中有 URLConnection 对象并使用以下代码获取 x-csrf-token

 URL obj = new URL(Util.ODATA_URL + "SO_BEATPSet");
                    URLConnection conn = obj.openConnection();
                    conn.setRequestProperty("Authorization", "Basic " + authStringEnc);
                    conn.addRequestProperty("x-csrf-token", "fetch");

......
......

 String server = conn.getHeaderField("x-csrf-token");

现在,在第一个成功完成后立即执行的第二个 AsyncTask 中,我遇到 403 错误。它基本上说我的 x-csrf-token 验证失败.

我 运行 一个简单的循环测试,其中我 运行 第一个 AsyncTask 三次,我得到了三个不同的令牌。 这就是我认为的问题所在。在 Second AsyncTask 中我使用 HttpPost 时,服务器需要一个与已经获取的令牌不同的令牌。

有什么方法可以在同一调用中获取并传递 X-csrf-token 吗? 我的第二个 AsyncTask 如下所示:

HttpPost postRequest = new HttpPost(url);

String credentials = UUSERNAME + ":" + PASSWORD;
                    String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

postRequest.addHeader("Authorization", "Basic " + base64EncodedCredentials);
postRequest.addHeader("x-csrf-token", X_CSRF_TOKEN); //   JHc4mG8siXrDtMSx0eD9wQ==

StringEntity entity = new StringEntity(XMLBuilders.BeatXMLBuilder());
entity.setContentType(new BasicHeader("Content-Type",
                            "application/atom+xml"));
postRequest.setEntity(entity);

您尝试过编码或解码 x-csrf-token 吗?

String tokenEncoded = URLEncoder.encode("xcsrftoken", "UTF-8")

String tokenDecoded = URLDecoder.decode("xcsrftoken", "UTF-8");

我曾经遇到过类似的问题,使用编码对我有用。

我最终能够获得成功的 POST 结果。但是,该解决方案对我来说似乎有点脏。但是,它确实暂时解决了我的问题。

我把下面的代码放在 AsyncTask

doInBackground() 方法中
 HttpClient httpclient = new DefaultHttpClient();
 HttpPost postRequest = new HttpPost(url);

 String credentials = USERNAME + ":" +PASSWORD;
 String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

  /**---------------------------------------------------------------------------------- **/
  /** THIS CODE BELOW CALLS THE SERVER FOR THE TOKEN AND PASSES THE VALUE TO THE SUBSEQUENT POSTREQUEST CALL.
      BY DOING THIS, THE SERVER IS NOT CALLED AGAIN BEFORE POSTREQUEST, AND USER GETS THE LATEST TOKEN **/
                        {
                            HttpGet httpget = new HttpGet(url);
                            httpget.setHeader("Authorization", "Basic " + base64EncodedCredentials);
                            httpget.setHeader("x-csrf-token", "fetch");

                            System.out.println("request:-------------------");
                            System.out.println(httpget.getRequestLine());
                            Header headers[] = httpget.getAllHeaders();
                            for (Header h : headers) {
                                System.out.println(h.getName() + "---:---- " + h.getValue());
                            }

                            HttpResponse res = httpclient.execute(httpget);                           
                            System.out.println("response:-------------------");
                            System.out.println(res.getStatusLine());

                            headers = res.getAllHeaders();
                            for (Header h : headers) {
                                System.out.println(h.getName() + "---:---- " + h.getValue());
                                if (h.getName().equals("x-csrf-token")) {
                                    X_CSRF_TOKEN = h.getValue();
                                }
                            }
                        }
  /**--------------------------------------------------------------------- **/


    // The main POST REQUEST
     postRequest.addHeader("Authorization", "Basic " + base64EncodedCredentials);
     postRequest.setHeader("x-csrf-token", X_CSRF_TOKEN); //   PASSING THE TOKEN GOTTEN FROM THE CODE ABOVE


     StringEntity entity = new StringEntity(myString);
     entity.setContentType(new BasicHeader("Content-Type",
                                "application/atom+xml"));
     postRequest.setEntity(entity);


     HttpResponse response = httpclient.execute(postRequest);
     Log.d("Http Post Response:", response.toString());

     String result = EntityUtils.toString(response.getEntity());
     Log.d("Http Response:", result);

     int responseCode = response.getStatusLine().getStatusCode();
     Log.d("Http Response: ", "Response code " + responseCode);

正如我在代码注释中所解释的那样,代码对服务器进行了另一次调用,而 HttpPost 已经进行了一次调用并获取了最新的令牌,该令牌又传递给后续的 POST请求。