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.

Shippi
fuente
Véase también stackoverflow.com/questions/9376549/…
Raedwald
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();
Universidad Angular
fuente
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)

Alex
fuente
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"));
León
fuente
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-

YanivJ
fuente
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

Johnny Lim
fuente
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!

atacomsiano
fuente
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!

Nidham
fuente
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();
Clairton Luz
fuente
Duplicado de stackoverflow.com/a/53394971 respuesta
Grigory Kislin