Выполнение аутентифицированных POST-запросов с помощью Spring RestTemplate для Android
У меня есть RESTful API, с которым я пытаюсь подключиться через Android и RestTemplate. Все запросы к API аутентифицируются с помощью HTTP-аутентификации, путем установки заголовков HttpEntity и затем использования метода RestTemplate exchange()
.
Все запросы GET отлично работают, но я не могу понять, как выполнить аутентифицированные POST-запросы. postForObject
и postForEntity
обрабатывать POST, но не имеют простого способа установить заголовки аутентификации.
Итак, для GET это отлично работает:
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);
Но POST, по-видимому, не работают с exchange()
, поскольку он никогда не отправляет настроенные заголовки, и я не вижу, как установить тело запроса с помощью exchange()
.
Каков самый простой способ сделать аутентифицированные POST-запросы из RestTemplate?
Ответы
Ответ 1
Хорошо нашел ответ. 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);
Ответ 2
Немного другой подход:
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);
Ответ 3
Очень полезно
У меня был немного другой сценарий, где я сам запрос xml был телом POST, а не параметром. Для этого можно использовать следующий код: публикация в качестве ответа на всякий случай, если кто-либо другой с подобной проблемой будет полезен.
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());
Ответ 4
Недавно я столкнулся с проблемой, когда я пытался пройти проверку подлинности при вызове REST с Java, и, хотя ответы в этом потоке (и других потоках) помогли, все еще было немного проб и ошибок в процессе его работы.
Что для меня работало, это кодирование учетных данных в Base64
и добавление их в качестве заголовков базовой авторизации. Затем я добавил их как HttpEntity
to 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);
}
}