Podstawowe uwierzytelnianie dla REST API przy użyciu spring restTemplate

86

Jestem zupełnie nowy w RestTemplate iw zasadzie w interfejsach API REST. Chcę odzyskać niektóre dane w mojej aplikacji za pośrednictwem Jira REST API, ale odzyskiwanie 401 Nieautoryzowane. Znaleziono i artykuł na temat dokumentacji jira rest api, ale tak naprawdę nie wiem, jak przepisać to do javy, ponieważ przykład używa linii poleceń z curl. Byłbym wdzięczny za wszelkie sugestie lub porady, jak przepisać:

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

do javy za pomocą szablonu podpórki sprężynowej. Gdzie ZnJlZDpmcmVk to ciąg znaków nazwa użytkownika: hasło zakodowany algorytmem base64. Dziękuję Ci bardzo.

Shippi
źródło
2
curl obsługuje uwierzytelnianie od razu po wyjęciu z pudełka, wystarczy podać nazwę użytkownika i hasło curl -u fred:fred, nie ma potrzeby stosowania niezgrabnych ręcznych nagłówków. To samo dotyczy wiosny.
divanov

Odpowiedzi:

150

Biorąc pod uwagę przykład na tej stronie , myślę, że byłby to najbardziej naturalny sposób na zrobienie tego, poprzez wypełnienie wartości nagłówka i przekazanie nagłówka do szablonu.

To ma wypełnić nagłówek 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);

A to jest przekazanie nagłówka do szablonu REST:

HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<Account> response = restTemplate.exchange(url, HttpMethod.GET, request, Account.class);
Account account = response.getBody();
Uniwersytet Angular
źródło
1
Dzięki - to zadziałało dla mnie. Musiałem zwrócić uwagę, że jeśli nie chcesz używać klasy org.apache.commons.codec.binary.Base64, a zamiast tego chciałbyś użyć klasy Android Base64: import android.util.Base64; to możesz zastąpić jedna linia powyżej z tym: byte [] base64CredsBytes = Base64.encode (plainCredsBytes, Base64.DEFAULT);
Simon
@jhadesdev Cześć, to zadziałało podczas wykonywania żądania GET. Chociaż nie daje 403, gdy jest w poście. Możesz mi pomóc?
Stefano Cazzola
8
java 8 możesz użyć Base64.getMimeEncoder (). encodeToString ()
Matt Broekhuis,
95

Możesz użyć RestTemplateBuilder z butami sprężynowymi

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

Zobacz dokumentację

(było przed SB 2.1.0 #basicAuthorization)

Alex
źródło
1
Uratowałeś mi dzień. Wielkie dzięki.
riccardo.cardin
4
Dzięki! To najszybszy i najłatwiejszy sposób.
Rajkishan Swami
1
Tak. to jest najszybszy sposób. Nie są wymagane żadne dodatkowe zależności.
Janath
3
@deprecated od 2.1.0 na korzyść #basicAuthentication (nazwa użytkownika w postaci ciągu, hasło w ciągu
znaków
2
Nie jest to dobre rozwiązanie, ponieważ dodaje nagłówek autoryzacji do każdego wysyłanego żądania RestTemplate.
attacomsian
22

(może) najłatwiej bez importowania spring-boot.

restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user", "password"));
Leon
źródło
2
Pamiętaj, że używanie przechwytywaczy powoduje, że przesyłanie strumieniowe przestaje działać. Oto dlaczego: exchange()-> doExecute(), -> createRequest(), -> InterceptingHttpAccessor.getRequestFactory()(od RestTemplaterozszerzeń InterceptingHttpAccessor). Jeśli są przechwytywacze, getRequestFactory()zwraca an InterceptingClientHttpRequestFactory, co tworzy InterceptingClientHttpRequests. Rozszerzają one AbstractBufferingClientHttpRequest`, które konwertuje strumień wejściowy na bajt [] (w celu przekazania do przechwytywaczy). Tak więc InputStream nie jest w rzeczywistości przesyłany strumieniowo.
mconner
17

Od Spring 5.1 możesz używać HttpHeaders.setBasicAuth

Utwórz nagłówek Basic Authorization:

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

Przekaż nagłówki do RestTemplate:

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

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

YanivJ
źródło
17

Referencyjna TestRestTemplateimplementacja Spring Boot w następujący sposób:

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

W szczególności zobacz poniższą metodę 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));
}

Podobnie można zrobić własny RestTemplatełatwo

przez dziedziczenie TestRestTemplatew następujący sposób:

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

Johnny Lim
źródło
pierwszy link prowadzi do 404
Zarremgregarrok
15

Istnieje wiele sposobów dodania podstawowego uwierzytelniania HTTP do RestTemplate.

1. Dla pojedynczego wniosku

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

Jeśli używasz Springa 5.1lub nowszego, nie jest już wymagane ręczne ustawianie nagłówka autoryzacji. headers.setBasicAuth()Zamiast tego użyj metody:

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

2. Dla grupy wniosków

@Service
public class RestService {

    private final RestTemplate restTemplate;

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

   // use `restTemplate` instance here
}

3. Na każdą prośbę

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

Mam nadzieję, że to pomoże!

attacomsian
źródło
Najlepsza odpowiedź. Każdy za to miły.
Rishi
6

Zamiast tworzenia wystąpienia w następujący sposób:

TestRestTemplate restTemplate = new TestRestTemplate();

Po prostu zrób to w ten sposób:

TestRestTemplate restTemplate = new TestRestTemplate(user, password);

U mnie działa, mam nadzieję, że pomaga!

Nidham
źródło
Wydaje się, że TestRestTemplate nie działa po aktualizacji sprężynowego rozruchu do 1.3.x
Vivek Sethi
1
Czy to nie powinno być używane do testów jednostkowych, a nie do wydania kodu?
David Bradley
0

Służy setBasicAuthdo definiowania poświadczeń

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

Następnie utwórz żądanie, jak wolisz.

Przykład:

HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, 
request, String.class);
String body = response.getBody();
Clairton Luz
źródło
Dublicate z stackoverflow.com/a/53394971 odpowiedź
Grigorij Kislin