90

I am completely new in RestTemplate and basically in the REST APIs also. I want to retrieve some data in my application via Jira REST API, but getting back 401 Unauthorised. Found and article on jira rest api documentation but don't really know how to rewrite this into java as the example uses the command line way with curl. I would appreciate any suggestion or advice how to rewrite:

curl -D- -X GET -H "Authorization: Basic ZnJlZDpmcmVk" -H "Content-Type: application/json" "http://kelpie9:8081/rest/api/2/issue/QA-31"

into java using spring rest template. Where the ZnJlZDpmcmVk is a base64 encoded string of username:password. Thank you very much.

shippi
  • 1,984
  • 5
  • 19
  • 27
  • See also http://stackoverflow.com/questions/9376549/resttemplate-basic-or-digest-authentication-with-the-current-httpclient-4-x – Raedwald Jul 30 '14 at 11:19
  • 2
    curl supports authentication out of the box, you just need to tell it username and passoword `curl -u fred:fred`, no need for clunky manual headers. The same goes for Spring. – divanov Sep 18 '14 at 08:28

8 Answers8

163

Taken from the example on this site, I think this would be the most natural way of doing it, by filling in the header value and passing the header to the template.

This is to fill in the header Authorization:

String plainCreds = "willie:p@ssword";
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);

HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);

And this is to pass the header to the REST template:

HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<Account> response = restTemplate.exchange(url, HttpMethod.GET, request, Account.class);
Account account = response.getBody();
Eddie
  • 8,370
  • 3
  • 41
  • 54
Angular University
  • 38,399
  • 15
  • 70
  • 79
  • 1
    Thanks - this worked for me. I had to point out that if you do not want to use the org.apache.commons.codec.binary.Base64 class and you would like to use the android Base64 class instead: import android.util.Base64;, you can replace the one line above with this: byte[] base64CredsBytes = Base64.encode(plainCredsBytes, Base64.DEFAULT); – Simon May 17 '15 at 19:09
  • @jhadesdev Hi, this worked for me when performing a GET request. Though it fails giving a 403 when in post. Can you help me? – Stefano Cazzola Jul 02 '15 at 22:16
  • 8
    java 8 you can use Base64.getMimeEncoder().encodeToString() – Matt Broekhuis Jan 02 '17 at 19:10
102

You may use spring-boot RestTemplateBuilder

@Bean
RestOperations rest(RestTemplateBuilder restTemplateBuilder) {
    return restTemplateBuilder.basicAuthentication("user", "password").build();
}

See documentation

(before SB 2.1.0 it was #basicAuthorization)

Alex
  • 1,812
  • 1
  • 15
  • 12
24

(maybe) the easiest way without importing spring-boot.

restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));
Leon
  • 2,632
  • 20
  • 34
  • 4
    Beware that using interceptors has a consequence that streaming no longer works. Here's why: `exchange()` -> `doExecute()`, -> `createRequest()`, -> `InterceptingHttpAccessor.getRequestFactory()` (since `RestTemplate` extends `InterceptingHttpAccessor`). If there are interceptors, `getRequestFactory()` returns an `InterceptingClientHttpRequestFactory`, which creates `InterceptingClientHttpRequest`s. These extend AbstractBufferingClientHttpRequest`, which converts the input stream to a byte[] (to hand off to the interceptors). So, an InputStream is not actually streamed. – mconner Apr 12 '19 at 19:27
21

As of Spring 5.1 you can use HttpHeaders.setBasicAuth

Create Basic Authorization header:

String username = "willie";
String password = ":p@ssword";
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
...other headers goes here...

Pass the headers to the RestTemplate:

HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<Account> response = restTemplate.exchange(url, HttpMethod.GET, request, Account.class);
Account account = response.getBody();

Documentation: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpHeaders.html#setBasicAuth-java.lang.String-java.lang.String-

YanivJ
  • 311
  • 2
  • 4
18

There are multiple ways to add the basic HTTP authentication to the RestTemplate.

1. For a single request

try {
    // request url
    String url = "https://jsonplaceholder.typicode.com/posts";

    // create auth credentials
    String authStr = "username:password";
    String base64Creds = Base64.getEncoder().encodeToString(authStr.getBytes());

    // create headers
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + base64Creds);

    // create request
    HttpEntity request = new HttpEntity(headers);

    // make a request
    ResponseEntity<String> response = new RestTemplate().exchange(url, HttpMethod.GET, request, String.class);

    // get JSON response
    String json = response.getBody();

} catch (Exception ex) {
    ex.printStackTrace();
}

If you are using Spring 5.1 or higher, it is no longer required to manually set the authorization header. Use headers.setBasicAuth() method instead:

// create headers
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("username", "password");

2. For a group of requests

@Service
public class RestService {

    private final RestTemplate restTemplate;

    public RestService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder
                .basicAuthentication("username", "password")
                .build();
    }

   // use `restTemplate` instance here
}

3. For each and every request

@Bean
RestOperations restTemplateBuilder(RestTemplateBuilder restTemplateBuilder) {
    return restTemplateBuilder.basicAuthentication("username", "password").build();
}

I hope it helps!

attacomsian
  • 1,430
  • 15
  • 16
17

Reference Spring Boot's TestRestTemplate implementation as follows:

https://github.com/spring-projects/spring-boot/blob/v1.2.2.RELEASE/spring-boot/src/main/java/org/springframework/boot/test/TestRestTemplate.java

Especially, see the addAuthentication() method as follows:

private void addAuthentication(String username, String password) {
    if (username == null) {
        return;
    }
    List<ClientHttpRequestInterceptor> interceptors = Collections
            .<ClientHttpRequestInterceptor> singletonList(new BasicAuthorizationInterceptor(
                    username, password));
    setRequestFactory(new InterceptingClientHttpRequestFactory(getRequestFactory(),
            interceptors));
}

Similarly, you can make your own RestTemplate easily

by inheritance like TestRestTemplate as follows:

https://github.com/izeye/samples-spring-boot-branches/blob/rest-and-actuator-with-security/src/main/java/samples/springboot/util/BasicAuthRestTemplate.java

Johnny Lim
  • 4,893
  • 5
  • 31
  • 49
6

Instead of instantiating as follows:

TestRestTemplate restTemplate = new TestRestTemplate();

Just do it like this:

TestRestTemplate restTemplate = new TestRestTemplate(user, password);

It works for me, I hope it helps!

Geoffrey Wiseman
  • 4,632
  • 3
  • 28
  • 46
Nidham
  • 61
  • 1
  • 1
0

Use setBasicAuth to define credentials

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("myUsername", myPassword);

Then create the request like you prefer.

Example:

HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, 
request, String.class);
String body = response.getBody();
Clairton Luz
  • 1,594
  • 17
  • 10