Базова автентифікація для REST API за допомогою spring restTemplate


86

Я абсолютно новачок у 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"

в Java за допомогою шаблону весняного відпочинку. Де ZnJlZDpmcmVk - це кодований рядок base64 ім'я користувача: пароль. Дуже дякую.



2
curl підтримує автентифікацію з коробки, вам просто потрібно повідомити його ім'я користувача та пароль curl -u fred:fred, не потрібно незграбних ручних заголовків. Те саме стосується і Весни.
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, а замість цього ви хочете використовувати клас Android64 Base: import android.util.Base64 ;, ви можете замінити один рядок зверху з цим: байт [] base64CredsBytes = Base64.encode (plainCredsBytes, Base64.DEFAULT);
Саймон

@jhadesdev Привіт, це спрацювало для мене при виконанні запиту GET. Хоча це не дає 403, коли на посаді. Можеш допомогти мені?
Стефано Каццола

8
Java 8, ви можете використовувати Base64.getMimeEncoder (). encodeToString ()
Метт Брукхуїс,

95

Ви можете використовувати spring-boot RestTemplateBuilder

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

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

(до SB 2.1.0 це було #basicAuthorization)


1
Ти врятував мій день. Дуже дякую.
riccardo.cardin

4
Дякую! Це найшвидший і найпростіший спосіб.
Раджкішан Свамі

1
Так. це найшвидший спосіб. Додаткові залежності не потрібні.
Джанат

3
@ припинено з 2.1.0 на користь #basicAuthentication (рядок імені користувача, рядок пароля)
rjdkolb

2
Це не є гарним рішенням, оскільки воно додасть заголовок авторизації до кожного запиту, що надсилається RestTemplate.
атакоміан

22

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

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

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

17

Станом на весну 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
Зарремгрегаррок,

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, здається, не працює після оновлення весняного завантаження до 1.3.x
Vivek Sethi

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

Дублікат stackoverflow.com/a/53394971 відповідь
Григорій Кіслін,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.