使用 spring restTemplate 对 REST API 进行基本身份验证

Posted

技术标签:

【中文标题】使用 spring restTemplate 对 REST API 进行基本身份验证【英文标题】:Basic authentication for REST API using spring restTemplate 【发布时间】:2014-03-22 03:09:35 【问题描述】:

我是 RestTemplate 的新手,基本上也是 REST API 的新手。我想通过 Jira REST API 在我的应用程序中检索一些数据,但返回 401 Unauthorized。在jira rest api documentation 上找到并发表文章,但不知道如何将其重写为 java,因为该示例使用 curl 的命令行方式。我将不胜感激任何关于如何重写的建议或建议:

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

使用spring rest模板进入java。其中 ZnJlZDpmcmVk 是用户名:密码的 base64 编码字符串。非常感谢。

【问题讨论】:

另见***.com/questions/9376549/… curl 支持开箱即用的身份验证,您只需告诉它用户名和密码curl -u fred:fred,无需笨重的手动标头。 Spring 也是如此。 【参考方案1】:

取自example on this site,我认为这是最自然的做法,通过填写标头值并将标头传递给模板。

这个是填表头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();

【讨论】:

谢谢 - 这对我有用。我必须指出,如果您不想使用 org.apache.commons.codec.binary.Base64 类,而是想使用 android Base64 类:import android.util.Base64;,您可以替换上面一行: byte[] base64CredsBytes = Base64.encode(plainCredsBytes, Base64.DEFAULT); @jhadesdev 嗨,这在执行 GET 请求时对我有用。虽然它在发布时未能给出 403。你能帮帮我吗? java 8 你可以使用 Base64.getMimeEncoder().encodeToString()【参考方案2】:

你可以使用 spring-boot RestTemplateBuilder

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

见documentation

(在 SB 2.1.0 之前它是 #basicAuthorization

【讨论】:

你拯救了我的一天。非常感谢。 谢谢!这是最快最简单的方法。 是的。这是最快的方法。不需要额外的依赖项。 这不是一个好的解决方案,因为它会为通过RestTemplate 发送的每个请求添加一个授权标头。【参考方案3】:

有多种方法可以将基本 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();

希望对你有帮助!

【讨论】:

最佳答案。每个都是善良的。【参考方案4】:

从 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-

【讨论】:

【参考方案5】:

(也许)不导入 spring-boot 的最简单方法。

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

【讨论】:

请注意,使用拦截器会导致流式传输不再有效。原因如下:exchange() -> doExecute(), -> createRequest(), -> InterceptingHttpAccessor.getRequestFactory()(因为 RestTemplate 扩展了 InterceptingHttpAccessor)。如果有拦截器,getRequestFactory() 返回一个InterceptingClientHttpRequestFactory,它会创建InterceptingClientHttpRequests。这些扩展了 AbstractBufferingClientHttpRequest`,它将输入流转换为 byte[](传递给拦截器)。因此,InputStream 实际上并没有流式传输。【参考方案6】:

参考Spring Boot的TestRestTemplate实现如下:

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【参考方案7】:

而不是像下面这样实例化:

TestRestTemplate restTemplate = new TestRestTemplate();

就这样吧:

TestRestTemplate restTemplate = new TestRestTemplate(user, password);

对我有用,希望对你有帮助!

【讨论】:

将 Spring Boot 升级到 1.3.x 后,TestRestTemplate 似乎无法正常工作 这不是应该用于单元测试而不是发布代码吗?【参考方案8】:

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

【讨论】:

***.com/a/53394971 答案的副本【参考方案9】:
HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(username, password);

然后继续这里其他人提到的相同程序:

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

【讨论】:

以上是关于使用 spring restTemplate 对 REST API 进行基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring RestTemplate 专题

Spring - WebClient & RestTemplate

Spring中RestTemplate的使用方法

Spring RestTemplate用法 Post Get Cookie

Spring的RestTemplate

Spring WebClient vs. RestTemplate