Создание аутентифицированных запросов POST с помощью Spring RestTemplate для Android
У меня есть RESTful API, с которым я пытаюсь связаться через Android и RestTemplate. Все запросы к API аутентифицируются с помощью HTTP-аутентификации, устанавливая заголовки HttpEntity и затем используя метод RestTemplate exchange()
.
Все запросы GET отлично работают таким образом, но я не могу понять, как выполнить аутентифицированные запросы POST. postForObject
и postForEntity
обрабатывают сообщения, но не имеют простого способа установить заголовки аутентификации.
Так что для GETs это работает отлично:
HttpAuthentication httpAuthentication = new HttpBasicAuthentication("username", "password");
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(httpAuthentication);
HttpEntity<?> httpEntity = new HttpEntity<Object>(requestHeaders);
MyModel[] models = restTemplate.exchange("/api/url", HttpMethod.GET, httpEntity, MyModel[].class);
Но сообщения, по-видимому, не работают с exchange()
, поскольку он никогда не отправляет настроенные заголовки, и я не вижу, как установить тело запроса с помощью exchange()
.
Какой самый простой способ сделать аутентифицированные запросы POST из RestTemplate?
4 ответа:
ОК нашел ответ.
exchange()
- это лучший способ. Как ни странно, классHttpEntity
не имеет методаsetBody()
(у него естьgetBody()
), но все же можно задать тело запроса через конструктор.// Create the request body as a MultiValueMap MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>(); body.add("field", "value"); // Note the body object as first parameter! HttpEntity<?> httpEntity = new HttpEntity<Object>(body, requestHeaders); MyModel model = restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity, MyModel.class);
Несколько иной подход:
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>(); headers.add("HeaderName", "value"); headers.add("Content-Type", "application/json"); RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); HttpEntity<ObjectToPass> request = new HttpEntity<ObjectToPass>(objectToPass, headers); restTemplate.postForObject(url, request, ClassWhateverYourControllerReturns.class);
Недавно я имел дело с проблемой, когда я пытался пройти аутентификацию, делая вызов REST из Java, и хотя ответы в этом потоке (и других потоках) помогли, все еще было немного проб и ошибок, связанных с его работой.
То, что работало для меня, было кодированием учетных данных в
Base64
и добавлением их в качестве основных заголовков авторизации. Затем я добавил их какHttpEntity
кrestTemplate.postForEntity
, что дало мне нужный ответ.Вот класс, который я написал для этого полностью (удлиняя RestTemplate):
public class AuthorizedRestTemplate extends RestTemplate{ private String username; private String password; public AuthorizedRestTemplate(String username, String password){ this.username = username; this.password = password; } public String getForObject(String url, Object... urlVariables){ return authorizedRestCall(this, url, urlVariables); } private String authorizedRestCall(RestTemplate restTemplate, String url, Object... urlVariables){ HttpEntity<String> request = getRequest(); ResponseEntity<String> entity = restTemplate.postForEntity(url, request, String.class, urlVariables); return entity.getBody(); } private HttpEntity<String> getRequest(){ HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Basic " + getBase64Credentials()); return new HttpEntity<String>(headers); } private String getBase64Credentials(){ String plainCreds = username + ":" + password; byte[] plainCredsBytes = plainCreds.getBytes(); byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); return new String(base64CredsBytes); } }
Очень полезно У меня был немного другой сценарий, где я запрос xml сам был телом поста, а не парамом. Для этого можно использовать следующий код-постинг в качестве ответа на случай, если кто-то другой, имеющий подобный вопрос, выиграет.
final HttpHeaders headers = new HttpHeaders(); headers.add("header1", "9998"); headers.add("username", "xxxxx"); headers.add("password", "xxxxx"); headers.add("header2", "yyyyyy"); headers.add("header3", "zzzzz"); headers.setContentType(MediaType.APPLICATION_XML); headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML)); final HttpEntity<MyXmlbeansRequestDocument> httpEntity = new HttpEntity<MyXmlbeansRequestDocument>( MyXmlbeansRequestDocument.Factory.parse(request), headers); final ResponseEntity<MyXmlbeansResponseDocument> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity,MyXmlbeansResponseDocument.class); log.info(responseEntity.getBody());