2012-04-27 45 views
34

Tôi có API RESTful Tôi đang cố kết nối với thông qua Android và RestTemplate. Tất cả các yêu cầu API được xác thực bằng Xác thực HTTP, thông qua thiết lập các tiêu đề của HttpEntity và sau đó sử dụng phương thức exchange() của RestTemplate.Thực hiện yêu cầu POST đã được xác thực bằng Spring RestTemplate cho Android

Tất cả yêu cầu GET hoạt động tốt theo cách này, nhưng tôi không thể tìm ra cách thực hiện các yêu cầu POST đã được xác thực. postForObjectpostForEntity xử lý POST nhưng không có cách nào dễ dàng để đặt tiêu đề Xác thực.

Vì vậy, đối GET, công trình vĩ đại này:

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

Nhưng POSTS dường như không làm việc với exchange() như nó không bao giờ gửi các tiêu đề tùy chỉnh và tôi không thấy làm thế nào để thiết lập các cơ thể yêu cầu sử dụng exchange().

Cách dễ nhất để thực hiện yêu cầu POST được xác thực từ RestTemplate là gì?

+1

requestHeaders.setAuthorization (httpAuthentication) .. Phương pháp undefined..no của nó như setAuthorization .. – DEADEND

Trả lời

75

Ok tìm thấy câu trả lời. exchange() là cách tốt nhất. Kỳ lạ là lớp HttpEntity không có phương thức setBody() (nó có getBody()), nhưng vẫn có thể đặt thân yêu cầu, thông qua hàm tạo.

// 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); 
+2

Nó ném một lỗi TypeMismatch Loại không phù hợp: không thể chuyển đổi từ ResponseEntity để MyModel .. tôi đoán nó phải được ResponseEntity mô hình = restTemplate.exchange ("/ api/url", HttpMethod.POST, httpEntity, MyModel.class); – Sid

+0

'MyModel myModel = restTemplate.exchange (completeServiceUrl, HttpMethod.GET, request, MyModel.class) .getBody()' sẽ giúp giải quyết vấn đề mà bạn đã đề cập – Isank

+0

THANKS. Điều này khiến tôi mất hai giờ, cho đến khi tôi tình cờ gặp bài đăng của bạn. – guenhter

7

Rất hữu ích Tôi có một kịch bản hơi khác khi tôi yêu cầu xml chính nó là nội dung của POST chứ không phải là thông số. Cho rằng mã sau đây có thể được sử dụng - Đăng như một câu trả lời chỉ trong trường hợp bất cứ ai khác có vấn đề tương tự sẽ được hưởng lợi.

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

cách tiếp cận Hơi khác nhau:

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

ObjectToPass ở đâu đến từ –

+0

@Ismail Iqbal - nó có thể là bất kỳ đối tượng nào có thông tin bạn cần truyền (ví dụ: private private john = Person ("John", 24);). Nó sẽ được chuyển thành tải trọng json và gửi đến máy chủ thông qua cơ thể yêu cầu – Andrey

7

thời gian gần đây tôi đã đối phó với một vấn đề khi tôi đã cố gắng để có được chứng thực qua trong khi thực hiện một cuộc gọi REST từ Java, và trong khi các câu trả lời trong chủ đề này (và các chủ đề khác) đã giúp, vẫn còn một chút thử thách và lỗi liên quan đến việc làm việc đó.

Điều gì đã hiệu quả đối với tôi là mã hóa bằng chứng xác thực trong Base64 và thêm chúng làm tiêu đề Ủy quyền cơ bản. Sau đó tôi đã thêm chúng dưới dạng HttpEntity đến restTemplate.postForEntity, đã cho tôi phản hồi mà tôi cần.

Đây là lớp tôi đã viết cho điều này trong đầy đủ (mở rộng 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); 
    } 
} 
Các vấn đề liên quan