72

我有一个 RESTful API,我试图通过 Android 和 RestTemplate 连接。所有对 API 的请求都通过 HTTP Authentication 进行身份验证,通过设置 HttpEntity 的标头,然后使用 RestTemplate 的exchange()方法。

所有 GET 请求都以这种方式工作得很好,但我无法弄清楚如何完成经过身份验证的 POST 请求。postForObjectpostForEntity处理 POST,但没有简单的方法来设置 Authentication 标头。

所以对于 GET,这很有效:

HttpAuthentication httpAuthentication = new HttpBasicAuthentication("username", "password");
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(httpAuthentication);

HttpEntity<?> httpEntity = new HttpEntity<Object>(requestHeaders);

MyModel[] models = restTemplate.exchange("/api/url", HttpMethod.GET, httpEntity, MyModel[].class);

但是 POST 显然无法使用,exchange()因为它从不发送自定义标头,而且我看不到如何使用exchange().

从 RestTemplate 发出经过身份验证的 POST 请求的最简单方法是什么?

4

4 回答 4

136

好的,找到了答案。exchange()是最好的方法。奇怪的是,HttpEntity该类没有setBody()方法(它有getBody()),但仍然可以通过构造函数设置请求主体。

// Create the request body as a MultiValueMap
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();     

body.add("field", "value");

// Note the body object as first parameter!
HttpEntity<?> httpEntity = new HttpEntity<Object>(body, requestHeaders);

ResponseEntity<MyModel> response = restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity, MyModel.class);
于 2012-05-01T20:45:09.123 回答
26

略有不同的做法:

MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("HeaderName", "value");
headers.add("Content-Type", "application/json");

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

HttpEntity<ObjectToPass> request = new HttpEntity<ObjectToPass>(objectToPass, headers);

restTemplate.postForObject(url, request, ClassWhateverYourControllerReturns.class);
于 2014-11-12T08:22:48.053 回答
12

我最近在处理一个问题,当时我试图在从 Java 进行 REST 调用时通过身份验证,虽然这个线程(和其他线程)中的答案有帮助,但在获取它时仍然需要一些试验和错误在职的。

对我有用的是编码凭据Base64并将它们添加为基本授权标头。然后我将它们添加为HttpEntityto restTemplate.postForEntity,这给了我所需的响应。

这是我为此编写的完整课程(扩展 RestTemplate):

public class AuthorizedRestTemplate extends RestTemplate{

    private String username;
    private String password;

    public AuthorizedRestTemplate(String username, String password){
        this.username = username;
        this.password = password;
    }

    public String getForObject(String url, Object... urlVariables){
        return authorizedRestCall(this, url, urlVariables);
    }

    private String authorizedRestCall(RestTemplate restTemplate, 
            String url, Object... urlVariables){
        HttpEntity<String> request = getRequest();
        ResponseEntity<String> entity = restTemplate.postForEntity(url, 
                request, String.class, urlVariables);
        return entity.getBody();
    }

    private HttpEntity<String> getRequest(){
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + getBase64Credentials());
        return new HttpEntity<String>(headers);
    }

    private String getBase64Credentials(){
        String plainCreds = username + ":" + password;
        byte[] plainCredsBytes = plainCreds.getBytes();
        byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
        return new String(base64CredsBytes);
    }
}
于 2015-06-26T14:34:37.577 回答
8

非常有用我有一个稍微不同的场景,我的请求 xml 本身就是 POST 的主体,而不是参数。为此,可以使用以下代码 - 发布作为答案,以防万一有类似问题的其他人受益。

    final HttpHeaders headers = new HttpHeaders();
    headers.add("header1", "9998");
    headers.add("username", "xxxxx");
    headers.add("password", "xxxxx");
    headers.add("header2", "yyyyyy");
    headers.add("header3", "zzzzz");
    headers.setContentType(MediaType.APPLICATION_XML);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
    final HttpEntity<MyXmlbeansRequestDocument> httpEntity = new HttpEntity<MyXmlbeansRequestDocument>(
            MyXmlbeansRequestDocument.Factory.parse(request), headers);
    final ResponseEntity<MyXmlbeansResponseDocument> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity,MyXmlbeansResponseDocument.class);
    log.info(responseEntity.getBody());
于 2012-07-24T13:07:29.997 回答