Базовая аутентификация для REST API с использованием Spring restTemplate


86

Я совершенно новичок в RestTemplate и в основном в API REST. Я хочу получить некоторые данные в своем приложении через Jira REST API, но получаю ответ 401 Unauthorized. Нашел и статью в документации 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"

в Java с помощью шаблона пружинной опоры. Где ZnJlZDpmcmVk - это строка имени пользователя: пароль в кодировке base64. Большое спасибо.



2
curl поддерживает аутентификацию из коробки, вам просто нужно указать имя пользователя и пароль curl -u fred:fred, нет необходимости в неуклюжих заголовках вручную. То же самое и с Spring.
divanov

Ответы:


150

Взято из примера на этом сайте , я думаю, что это был бы наиболее естественный способ сделать это, заполнив значение заголовка и передав заголовок в шаблон.

Это для заполнения шапки 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);

И это для передачи заголовка в шаблон REST:

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

1
Спасибо, у меня это сработало. Я должен был указать, что если вы не хотите использовать класс org.apache.commons.codec.binary.Base64 и вместо этого хотели бы использовать класс Android Base64: import android.util.Base64;, вы можете заменить на одну строку выше: byte [] base64CredsBytes = Base64.encode (plainCredsBytes, Base64.DEFAULT);
Саймон

@jhadesdev Привет, это сработало для меня при выполнении запроса GET. Хотя при публикации он не дает 403 балла. Вы можете мне помочь?
Стефано Каццола 02

8
java 8, вы можете использовать Base64.getMimeEncoder (). encodeToString ()
Мэтт

95

Вы можете использовать RestTemplateBuilder с весенней загрузкой

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

См. Документацию

(до СБ 2.1.0 было #basicAuthorization)


1
Ты спас мне день. Большое спасибо.
riccardo.cardin

4
Благодаря! Это самый быстрый и простой способ.
Раджкишан Свами

1
Да. это самый быстрый способ. Никаких дополнительных зависимостей не требуется.
Janath

3
@deprecated с 2.1.0 в пользу #basicAuthentication (String username, String password)
rjdkolb

2
Это не лучшее решение, так как оно добавит заголовок авторизации к каждому отправляемому запросу RestTemplate.
аттакомсиан

22

(возможно) самый простой способ без импорта spring -boot.

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

2
Помните, что использование перехватчиков приводит к тому, что потоковая передача больше не работает. Вот почему: exchange()-> doExecute(), -> createRequest(), -> InterceptingHttpAccessor.getRequestFactory()(поскольку RestTemplateрасширяется InterceptingHttpAccessor). Если есть перехватчики, getRequestFactory()возвращает InterceptingClientHttpRequestFactory, что создает InterceptingClientHttpRequests. Они расширяют AbstractBufferingClientHttpRequest`, который преобразует входной поток в byte [] (для передачи перехватчикам). Итак, InputStream на самом деле не передается.
mconner

17

Начиная с Spring 5.1 вы можете использовать HttpHeaders.setBasicAuth

Создать заголовок базовой авторизации:

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

Передайте заголовки в RestTemplate:

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

Документация: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpHeaders.html#setBasicAuth-java.lang.String-java.lang.String-


17

Ссылка на TestRestTemplateреализацию Spring Boot выглядит следующим образом:

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

В частности, см. Метод addAuthentication () следующим образом:

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

Точно так же вы можете RestTemplateлегко сделать свой собственный

по наследству TestRestTemplate:

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


первая ссылка ведет к 404
Zarremgregarrok

15

Есть несколько способов добавить базовую HTTP-аутентификацию в RestTemplate.

1. Для разового запроса

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

Если вы используете Spring 5.1или более позднюю версию, больше не требуется вручную устанавливать заголовок авторизации. headers.setBasicAuth()Вместо этого используйте метод:

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

2. Для группы запросов

@Service
public class RestService {

    private final RestTemplate restTemplate;

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

   // use `restTemplate` instance here
}

3. По каждому запросу

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

Я надеюсь, что это помогает!


Лучший ответ. Каждому по-своему.
Риши

6

Вместо создания следующего экземпляра:

TestRestTemplate restTemplate = new TestRestTemplate();

Просто сделайте это так:

TestRestTemplate restTemplate = new TestRestTemplate(user, password);

У меня работает, надеюсь поможет!


TestRestTemplate, похоже, не работает после обновления Spring Boot до 1.3.x
Вивек Сетхи

1
Разве это не должно использоваться для модульных тестов, а не для выпуска кода?
Дэвид Брэдли

0

Используйте setBasicAuthдля определения учетных данных

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

Затем создайте запрос, как вы предпочитаете.

Пример:

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.