【问题标题】:Making authenticated POST requests with Spring RestTemplate for Android使用 Spring RestTemplate for Android 发出经过身份验证的 POST 请求
【发布时间】:2012-05-08 15:46:07
【问题描述】:

我有一个 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 请求的最简单方法是什么?

【问题讨论】:

  • requestHeaders.setAuthorization(httpAuthentication)..它的未定义..没有setAuthorization之类的方法..

标签: java android spring rest resttemplate


【解决方案1】:

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

【讨论】:

  • 它会抛出 TypeMismatch 错误 Type mismatch: cannot convert from ResponseEntity to MyModel .. 我猜应该是 ResponseEntity model = restTemplate.exchange("/api/url", HttpMethod .POST, httpEntity, MyModel.class);
  • MyModel myModel = restTemplate.exchange(completeServiceUrl, HttpMethod.GET, request, MyModel.class).getBody() 将帮助解决您提到的问题
  • 谢谢。这花了我两个小时,直到我偶然发现了你的帖子。
  • 为了在最近的 Spring Security 环境中工作,您必须禁用 CSRF 保护,例如 http.csrf().disable()
【解决方案2】:

略有不同的方法:

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

【讨论】:

  • ObjectToPass 是从哪里来的
  • @Ismail Iqbal - 它可以是您需要传递信息的任何对象(例如 private Person john = Person("John", 24);)。它将被转换为 json 有效载荷并通过请求正文发送到服务器
【解决方案3】:

我最近在处理一个问题,当时我试图在从 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);
    }
}

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 2021-05-23
      • 2021-12-31
      • 2016-03-20
      • 1970-01-01
      • 2019-03-29
      相关资源
      最近更新 更多