使用 spring restTemplate 对 REST API 进行基本身份验证

我在 RestTemplate 和基本上在 REST API 中都是全新的。我想检索一些数据在我的应用程序通过 Jira REST API,但回来401未经授权。在 Jira rest api 文件上找到并写了一篇文章,但是不知道如何将其重写到 Java 中,因为示例使用 cURL 命令行方式。如果您能提出任何改写的建议或意见,我将不胜感激:

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

其中 ZnJlZDpmcmVk 是一个 base64编码的用户名: 密码字符串。

227291 次浏览

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

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

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!

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)

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

restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));

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-

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!

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();
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);

then continue with the same procedure mentioned by the others here:

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

I'm using spring version 5.3.15 for my unit test environment. I used withBasicAuth for my tests :

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyTestClass {
...
@Autowired
private TestRestTemplate restTemplate;
...
@Test
@SneakyThrows
public void TestGetSettings(){
DtoClass dtoClass  = this.restTemplate
.withBasicAuth(UserServices.DEFAULT_USER, UserServices.DEFAULT_PASSWORD)
.getForObject(String.format("http://localhost:%d/setting",
port), DtoClass.class);
assertThat(dtoClass.getClientAddress()).isNotEmpty();
}
...
}


As you see this method only work for basic authentication. If you look at the details of the withBasicAuth method, you will find that the method source will be like this:

// TestRestTemplate.java file:
...
public class TestRestTemplate {
...
private final RestTemplateBuilder builder;
...
public TestRestTemplate withBasicAuth(String username, String password) {
TestRestTemplate template = new TestRestTemplate(this.builder, username, password, this.httpClientOptions);
...
}
}


As a result, for other types of authentication you can use the RestTemplateBuilder as a builder which is mentioned in other answers.

Follow Step By Step

I added Client Credentials In application.Properties file like below...

http.basicauth.username = yourUserName
http.basicauth.password = yourPassword

And , Then I created one class With two fields Because I'm loading those two fields from the Application.Properties file : username and password . Make sure your class is annotated with @Component..

@Value("${http.basicauth.username}")
private String username;


@Value("${http.basicauth.password}")
private String password;

And Then , You need to autowired above class From Wherever you want..

// I'm getting a username and password from application.properties file
String userCredentials = referenceClassName.getUsername()+":"+referenceClassName.getPassword();
// Encoded User Credentials and Convert it into a String
String encodedUserCredentials= Base64.getMimeEncoder().encodeToString(userCredentialsBytes.getBytes());
headers.set("Authorization", "Basic " +base64UserCredentials);


HttpEntity request = new HttpEntity(headers);
String url = "externalUrl";
// Getting a Json String body
String body = restTemplate.exchange(url,HttpMethod.GET,request,String.class).getBody();


Note :: For getting an Access Token from String Json body  , That's why  I converted it into a Json Object
JsonObject tokenJsonObject = new JsonParser().parse(body).getAsJsonObject();
// Getting access token as string from tokenJsonObject
String accessToken = tokenJsonObject.has("access_token") && !tokenJsonObject.get("access_token").isJsonNull() ? tokenJsonObject.get("access_token").getAsString() : "";

If you have any concerns, please let me know in comments..Hope It will helpful to you..

I have been using Spring above 5.1.x

// create headers for basic auth


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