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

问题描述 投票:0回答:3

我必须将 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
三次,并且得到了三个不同的令牌。 我认为这就是问题所在。当我在第二个
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);
android http http-headers odata androidhttpclient
3个回答
2
投票

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

我将如下代码放入

doInBackground()
AsyncTask

方法中
 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 请求。


0
投票

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

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

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

我曾经遇到过类似的问题,使用编码为我解决了这个问题。


0
投票

我在Java中发出两个请求时遇到了同样的错误。具体来说,当我发出 GET 令牌请求时,我每次都会收到不同的令牌。因此,当我将新令牌传递给 POST 调用时,它返回了 403 Forbidden 错误,并显示消息“CSRF 令牌验证失败”。

解决方案是像这样初始化 HttpClient:

HttpClient client = HttpClient.newBuilder().cookieHandler(new CookieManager()).build()

© www.soinside.com 2019 - 2024. All rights reserved.