我有一个RESTful API,我试图通过Android和RestTemplate连接。所有对API的请求都通过HTTP身份验证进行身份验证,方法是设置HttpEntity的标头,然后使用RestTemplate的exchange()
方法。
所有GET请求都以这种方式运行,但我无法弄清楚如何完成经过身份验证的POST请求。 postForObject
和postForEntity
处理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请求的最简单方法是什么?
答案 0 :(得分:100)
好的找到了答案。 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);
MyModel model = restTemplate.exchange("/api/url", HttpMethod.POST, httpEntity, MyModel.class);
答案 1 :(得分:19)
略有不同的方法:
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);
答案 2 :(得分:9)
当我在尝试从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);
}
}
答案 3 :(得分:7)
非常有用 我有一个稍微不同的场景,我请求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());