使用 Spring RestTemplate 为 Android 制作经过身份验证的 POST 请求

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

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

因此,对 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 请求的最简单方法是什么?

255364 次浏览

找到答案了。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);

非常有用 我有一个稍微不同的场景,请求 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());

略有不同的方法:

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

我最近正在处理一个问题,当我试图在从 Java 发出 REST 调用时通过身份验证,尽管这个线程(和其他线程)中的答案有所帮助,但在让它工作时仍然有一些尝试和错误。

对我有效的方法是在 Base64中对凭据进行编码,并将它们添加为基本授权头。然后我将它们作为 HttpEntity添加到 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);
}
}