2013-08-13 5 views
0

Я работаю над API-интерфейсом Android для нового веб-сайта моей организации. Новый веб-сайт написан в Rails, а проверка подлинности выполняется следующим образом: я делаю POST-запрос на URL-адрес сайта с учетными данными, и я возвращаю токен CSRF и файл cookie для менеджера файлов cookie Android. Затем я передаю токен CSRF для аутентифицированных функций.Подлинность Rails от API Android с HttpPost

Моя проблема связана с функцией UploadCSV, которую я пытаюсь реализовать. Я подражал запросу, создаваемому пользовательским интерфейсом веб-сайта при нажатии кнопки «Загрузить CSV», но сайт отказывается от моего запроса и говорит мне, что он не может проверить токен 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.

ответ

0

Видимо, ответ заключается не в использовании HttpPost. Я изменил свой запрос на использование HttpURLConnection, и это удалось.

URL url = new URL(baseURL+"/projects/"+projectId+"/CSVUpload?authenticity_token="+URLEncoder.encode(authToken, "UTF-8")); 
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
connection.setDoOutput(true); 
connection.setRequestMethod("POST"); 

MultipartEntity entity = new MultipartEntity(); 
entity.addPart("utf8", new StringBody("\u2713", "text/plain", Charset.forName("UTF-8"))); 
entity.addPart("csv", new FileBody(csvToUpload, "text/csv")); 

connection.setRequestProperty("Content-Type", entity.getContentType().getValue()); 
OutputStream out = connection.getOutputStream(); 
try { 
    entity.writeTo(out); 
} finally { 
    out.close(); 
} 
connection.getResponseCode(); 

Это немного менее лаконичный, но он работает.

0

Вы пробовали отправить токен в заголовке X-CSRF-Token? Я предполагаю, что некоторые из ваших запросов не жалуются, потому что они используют GET, который пропускает проверку.

Если вы хотите обходить это для POST, вы можете добавить skip_before_filter :verify_authenticity_token, хотя я упоминаю об этом с предостережением, которое не рекомендуется.

+0

Извините за предыдущие комментарии, я неправильно понял. Я просто попробовал передать свой токен, как с HTTP-заголовком X-CSRF-Token, но это не изменило ситуацию. – Nick

Смежные вопросы