Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a RESTful API I'm trying to connect with via Android and RestTemplate. All requests to the API are authenticated with HTTP Authentication, through setting the headers of the HttpEntity and then using RestTemplate's exchange() method.

All GET requests work great this way, but I cannot figure out how to accomplish authenticated POST requests. postForObject and postForEntity handle POSTs, but have no easy way to set the Authentication headers.

So for GETs, this works great:

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);

But POSTs apparently don't work with exchange() as it never sends the customized headers and I don't see how to set the request body using exchange().

What is the easiest way to make authenticated POST requests from RestTemplate?

requestHeaders.setAuthorization(httpAuthentication).. its undefined..no method such as setAuthorization.. – deadend Sep 12, 2017 at 9:00

Ok found the answer. exchange() is the best way. Oddly the HttpEntity class doesn't have a setBody() method (it has getBody()), but it is still possible to set the request body, via the constructor.

// 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);
ResponseEntity<MyModel> response = restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity, MyModel.class);
                It throws a TypeMismatch error  Type mismatch: cannot convert from ResponseEntity<MyModel> to MyModel ..  I guess it should be      ResponseEntity<MyModel> model =    restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity,     MyModel.class);
– Sid
                Apr 7, 2016 at 10:19
                MyModel myModel = restTemplate.exchange(completeServiceUrl, HttpMethod.GET, request, MyModel.class).getBody() will help solve the problem that you mentioned
– isank-a
                Aug 31, 2017 at 16:07
                For this to work in recent Spring Security environments you MUSTdisable CSRF-Protection like http.csrf().disable()
– M46
                Jul 23, 2018 at 17:53

Slightly different approach:

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);
                @Ismail Iqbal - it can be any object with info you need to pass (for example private Person john = Person("John", 24);). It will be converted to json payload and sent to the server via request body
– Andrew
                Oct 18, 2016 at 10:38

I was recently dealing with an issue when I was trying to get past authentication while making a REST call from Java, and while the answers in this thread (and other threads) helped, there was still a bit of trial and error involved in getting it working.

What worked for me was encoding credentials in Base64 and adding them as Basic Authorization headers. I then added them as an HttpEntity to restTemplate.postForEntity, which gave me the response I needed.

Here's the class I wrote for this in full (extending 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);

Very useful I had a slightly different scenario where I the request xml was itself the body of the POST and not a param. For that the following code can be used - Posting as an answer just in case anyone else having similar issue will benefit.

    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());
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.