我正在为我组织的新网站开发 Android 客户端 API。新网站是用 Rails 编写的,身份验证按如下方式完成:我使用凭据向网站的登录 URL 发出 POST 请求,并向 Android 的 cookie 管理器返回一个 CSRF 令牌和一个 cookie。然后我将 CSRF 令牌传递给经过身份验证的函数。
我的问题是我正在尝试实现的 UploadCSV 函数。当您单击“上传 CSV”按钮时,我模仿了网站 UI 生成的请求,但该网站拒绝了我的请求并告诉我它无法验证我的 CSRF 令牌。同样的令牌也适用于其他经过身份验证的功能,我终生无法弄清楚原因。
这是我创建请求的函数:
URI url = new URI(baseURL+"/projects/"+projectId+"/CSVUpload");
HttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,null,Charset.forName(HTTP.UTF_8));
entity.addPart("authenticity_token", new StringBody(authToken));
entity.addPart("csv", new FileBody(csvToUpload));
entity.addPart("utf8", new StringBody("\u2713", "text/plain", Charset.forName("UTF-8")));
httpPost.setEntity(entity);
client.execute(httpPost);
这是服务器日志消息:
Started POST "/projects/7/CSVUpload" for ***.**.***.** at 2013-08-13 08:38:13 -0400
Processing by DataSetsController#uploadCSV as HTML
Parameters: {"authenticity_token"=>"OvJanht9/GZu90rcRrR3YH94M8Ukamr5OLp/qiOEZAY=", "csv"=>#<ActionDispatch::Http::UploadedFile:0x007fd6ae12a7a0 @original_filename="weird.csv", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"csv\"; filename=\"weird.csv\"\r\nContent-Type: application/octet-stream\r\n", @tempfile=#<File:/var/folders/9q/v5l53m3141d4cbrd8w07g0sm0000gn/T/RackMultipart20130813-55943-5v1kp8>>, "utf8"=>"✓", "id"=>"7"}
WARNING: Can't verify CSRF token authenticity
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Redirected to http://***.**.**.**:3000/
Filter chain halted as :authorize rendered or redirected
Completed 302 Found in 12ms (ActiveRecord: 0.3ms)
我的 API 中的其他函数使用 HTTPUrlConnection 方法来发送他们的 POST 请求,并且这些验证很好。我想使用 HttpPost 发送 MultipartEntity。