Autenticación básica para API REST usando Spring RestTemplate


83

Soy completamente nuevo en RestTemplate y básicamente también en las API REST. Quiero recuperar algunos datos en mi aplicación a través de la API REST de Jira, pero recupero 401 No autorizado. Se encontró un artículo sobre la documentación de la API de rest de jira, pero realmente no sé cómo reescribir esto en Java, ya que el ejemplo usa la línea de comandos con curl. Agradecería cualquier sugerencia o consejo sobre cómo reescribir:

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

en java usando la plantilla de descanso de primavera. Donde ZnJlZDpmcmVk es una cadena codificada en base64 de nombre de usuario: contraseña. Muchas gracias.



2
curl admite la autenticación desde el primer momento, solo necesita indicarle el nombre de usuario y la contraseña curl -u fred:fred, sin necesidad de encabezados manuales torpes. Lo mismo ocurre con la primavera.
divanov

Respuestas:


148

Tomado del ejemplo de este sitio , creo que esta sería la forma más natural de hacerlo, completando el valor del encabezado y pasando el encabezado a la plantilla.

Esto es para completar el encabezado 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);

Y esto es para pasar el encabezado a la plantilla REST:

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

1
Gracias, esto funcionó para mí. Debo señalar que si no desea usar la clase org.apache.commons.codec.binary.Base64 y desea usar la clase Android Base64 en su lugar: import android.util.Base64 ;, puede reemplazar el una línea arriba con esto: byte [] base64CredsBytes = Base64.encode (plainCredsBytes, Base64.DEFAULT);
Simon

@jhadesdev Hola, esto funcionó para mí al realizar una solicitud GET. Aunque falla dando un 403 cuando está en el puesto. ¿Me puedes ayudar?
Stefano Cazzola

7
java 8 puede usar Base64.getMimeEncoder (). encodeToString ()
Matt Broekhuis

92

Puede usar Spring-boot RestTemplateBuilder

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

Ver documentación

(antes de SB 2.1.0 lo era #basicAuthorization)


1
Salvaste mi día. Muchas gracias.
riccardo.cardin

4
¡Gracias! Ésta es la forma más rápida y sencilla.
Rajkishan Swami

1
Si. esta es la forma más rápida. No se requieren dependencias adicionales.
Janath

3
@deprecated desde 2.1.0 a favor de #basicAuthentication (String username, String password)
rjdkolb

1
No es una buena solución, ya que agregaría un encabezado de autorización a todas y cada una de las solicitudes enviadas RestTemplate.
attacomsian

22

(quizás) la forma más fácil sin importar spring-boot.

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

2
Tenga en cuenta que el uso de interceptores tiene como consecuencia que la transmisión ya no funcione. He aquí por qué: exchange()-> doExecute(), -> createRequest(), -> InterceptingHttpAccessor.getRequestFactory()(ya que se RestTemplateextiende InterceptingHttpAccessor). Si hay interceptores, getRequestFactory()devuelve an InterceptingClientHttpRequestFactory, que crea InterceptingClientHttpRequests. Estos amplían AbstractBufferingClientHttpRequest`, que convierte el flujo de entrada en un byte [] (para transferirlo a los interceptores). Por lo tanto, un InputStream no se transmite en realidad.
mconner

17

A partir de Spring 5.1 puedes usar HttpHeaders.setBasicAuth

Crear encabezado de autorización básica:

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

Pase los encabezados a RestTemplate:

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

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


17

Haga referencia a la TestRestTemplateimplementación de Spring Boot de la siguiente manera:

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

Especialmente, vea el método addAuthentication () de la siguiente manera:

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

Del mismo modo, puedes hacer el tuyo propio RestTemplatefácilmente

por herencia TestRestTemplatecomo sigue:

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


el primer enlace conduce a 404
Zarremgregarrok

14

Hay varias formas de agregar la autenticación HTTP básica a RestTemplate.

1. Para una sola solicitud

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

Si está utilizando Spring 5.1o superior, ya no es necesario configurar manualmente el encabezado de autorización. Utilice el headers.setBasicAuth()método en su lugar:

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

2. Para un grupo de solicitudes

@Service
public class RestService {

    private final RestTemplate restTemplate;

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

   // use `restTemplate` instance here
}

3. Para todas y cada una de las solicitudes

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

¡Espero que ayude!


La mejor respuesta. Cada uno por su amabilidad.
Rishi

6

En lugar de crear instancias de la siguiente manera:

TestRestTemplate restTemplate = new TestRestTemplate();

Solo hazlo así:

TestRestTemplate restTemplate = new TestRestTemplate(user, password);

Funciona para mí, ¡espero que ayude!


TestRestTemplate no parece funcionar después de actualizar Spring Boot a 1.3.x
Vivek Sethi

1
¿No se supone que esto debe usarse para pruebas unitarias, no para liberar código?
David Bradley

0

Úselo setBasicAuthpara definir credenciales

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

Luego crea la solicitud como prefieras.

Ejemplo:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.