Faire des requêtes POST authentifiées avec Spring RestTemplate pour Android

j'ai une API RESTful avec laquelle j'essaie de me connecter via Android et RestTemplate. Toutes les requêtes vers L'API sont authentifiées par L'authentification HTTP, en définissant les en-têtes de L'entité HttpEntity et en utilisant exchange() méthode.

toutes les requêtes GET fonctionnent très bien de cette façon, mais je ne peux pas trouver comment accomplir les requêtes POST authentifiées. postForObject et postForEntity manipuler les poteaux, mais n'ont pas de façon facile de définir les en-têtes D'authentification.

Donc, pour l'Obtient, cela fonctionne très bien:

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

Mais les Messages ne semblent pas fonctionner avec exchange() comme il n'envoie jamais les en-têtes personnalisés et je ne vois pas comment configurer le corps de la requête en utilisant exchange().

Quelle est la façon la plus simple de faire des requêtes POST authentifiées de RestTemplate?

40
demandé sur Nick Daugherty 2012-04-28 01:53:50

4 réponses

Ok trouvé la réponse. exchange() est le meilleur moyen. Bizarrement HttpEntity la classe n'a pas de setBody() méthode (elle a getBody()), mais il est toujours possible de définir le corps de la requête, via le constructeur.

// 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);
87
répondu Nick Daugherty 2012-05-19 02:25:53

approche Légèrement différente:

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);
16
répondu Andrey 2014-11-12 08:22:48

j'ai récemment eu affaire à un problème lorsque j'ai essayé de passer l'authentification tout en faisant un appel de repos depuis Java, et bien que les réponses dans ce thread (et d'autres threads) ont aidé, il y avait encore un peu d'essai et d'erreur impliqué dans le fait de le faire fonctionner.

ce qui a fonctionné pour moi était d'encoder les références dans Base64 et les ajouter comme en-têtes D'autorisation de base. J'ai ensuite ajouté un HttpEntityrestTemplate.postForEntity, ce qui m'a donné la réponse dont j'avais besoin.

Voici le classe, j'ai écrit pour cet intégral (extension de 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);
    }
}
8
répondu zacran 2015-12-10 13:28:44

Très utile J'ai eu un scénario légèrement différent où la requête xml était elle-même le corps du POST et non un param. Pour cela, le code suivant peut être utilisé - poster comme réponse juste au cas où quelqu'un d'autre ayant une question similaire bénéficiera.

    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());
7
répondu Soumya 2012-07-24 13:07:29