Ich muss Ressourcen von meinem Server abrufen, indem ich mithilfe von RestTemplate eine GET-Anforderung mit einigen Autorisierungsheadern sende.
Nachdem ich die Dokumente durchgesehen hatte, bemerkte ich, dass keine der GET-Methoden Header als Parameter akzeptiert und die einzige Möglichkeit, Header wie accept und Authorization zu senden, die Verwendung der Exchange- Methode ist.
Da es sich um eine sehr einfache Aktion handelt, frage ich mich, ob mir etwas fehlt und ob es einen anderen, einfacheren Weg gibt, dies zu tun.
quelle
Sie können
postForObject
mit einem verwendenHttpEntity
. Es würde so aussehen:HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", "Bearer "+accessToken); HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers); String result = restTemplate.postForObject(url, entity, String.class);
In einer GET-Anfrage würden Sie normalerweise keinen Text senden (dies ist zulässig, hat aber keinen Zweck). Die Möglichkeit, Header hinzuzufügen, ohne die RestTemplate anders zu verkabeln, besteht darin, die Methoden
exchange
oderexecute
direkt zu verwenden. Die get-Kurzschriften unterstützen keine Header-Modifikation.Die Asymmetrie ist auf den ersten Blick etwas seltsam, vielleicht wird dies in zukünftigen Versionen von Spring behoben.
quelle
restTemplate.postForEntity(url, entity, String.class)
funktioniert auch gut.getForObject
mit einer solchen Unterschrift.Hier ist ein supereinfaches Beispiel mit grundlegender Authentifizierung, Headern und Ausnahmebehandlung ...
private HttpHeaders createHttpHeaders(String user, String password) { String notEncoded = user + ":" + password; String encodedAuth = "Basic " + Base64.getEncoder().encodeToString(notEncoded.getBytes()); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.add("Authorization", encodedAuth); return headers; } private void doYourThing() { String theUrl = "http://blah.blah.com:8080/rest/api/blah"; RestTemplate restTemplate = new RestTemplate(); try { HttpHeaders headers = createHttpHeaders("fred","1234"); HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class); System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody()); } catch (Exception eek) { System.out.println("** Exception: "+ eek.getMessage()); } }
quelle
Alle diese Antworten scheinen unvollständig und / oder kludges zu sein. Wenn Sie sich die RestTemplate-Oberfläche ansehen, sieht es sicher so aus, als ob eine
ClientHttpRequestFactory
Injektion in die Benutzeroberfläche vorgesehen ist. Anschließend wird diese requestFactory zum Erstellen der Anforderung verwendet, einschließlich aller Anpassungen von Headern, Text und Anforderungsparametern.Sie benötigen entweder ein Universal
ClientHttpRequestFactory
, um es in eine einzelne Freigabe einzufügen,RestTemplate
oder Sie müssen eine neue Vorlageninstanz über abrufennew RestTemplate(myHttpRequestFactory)
.Leider ist es nicht trivial, eine solche Factory zu erstellen, selbst wenn Sie nur einen einzelnen Autorisierungsheader festlegen möchten. Dies ist ziemlich frustrierend, wenn man bedenkt, was für eine häufige Anforderung dies wahrscheinlich ist, aber es ermöglicht zumindest eine einfache Verwendung, wenn beispielsweise Wenn Ihr Authorization-Header aus Daten erstellt werden kann, die in einem Spring-Security-
Authorization
Objekt enthalten sind, können Sie eine Factory erstellen, die den ausgehenden AuthorizationHeader für jede Anforderung festlegt, indem SieSecurityContextHolder.getContext().getAuthorization()
den Header ausführen und dann mit entsprechenden Nullprüfungen füllen. Jetzt haben alle ausgehenden Restaufrufe, die mit diesem RestTemplate getätigt werden, den richtigen Autorisierungsheader.Ohne mehr Gewicht auf den HttpClientFactory-Mechanismus zu legen, der einfach zu überladende Basisklassen für häufige Fälle wie das Hinzufügen eines einzelnen Headers zu Anforderungen bereitstellt, sind die meisten der nützlichen Methoden
RestTemplate
Zeitverschwendung, da sie nur selten verwendet werden können .Ich würde gerne sehen, dass so etwas Einfaches zur Verfügung gestellt wird
@Configuration public class MyConfig { @Bean public RestTemplate getRestTemplate() { return new RestTemplate(new AbstractHeaderRewritingHttpClientFactory() { @Override public HttpHeaders modifyHeaders(HttpHeaders headers) { headers.addHeader("Authorization", computeAuthString()); return headers; } public String computeAuthString() { // do something better than this, but you get the idea return SecurityContextHolder.getContext().getAuthorization().getCredential(); } }); } }
Im Moment ist es schwieriger, mit der Schnittstelle der verfügbaren ClientHttpRequestFactory zu interagieren. Noch besser wäre ein abstrakter Wrapper für vorhandene Factory-Implementierungen, der sie wie ein einfacheres Objekt wie AbstractHeaderRewritingRequestFactory aussehen lässt, um nur diese eine Funktionalität zu ersetzen. Im Moment sind sie sehr allgemein gehalten, so dass selbst das Schreiben dieser Wrapper ein komplexes Stück Forschung ist.
quelle
Heutzutage wird so etwas wie das Folgende ausreichen:
HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(accessToken); restTemplate.exchange(RequestEntity.get(new URI(url)).headers(headers).build(), returnType);
quelle
Eine einfache Lösung wäre, statische http-Header zu konfigurieren, die für alle Aufrufe in der Bean-Konfiguration von RestTemplate benötigt werden:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate getRestTemplate(@Value("${did-service.bearer-token}") String bearerToken) { RestTemplate restTemplate = new RestTemplate(); restTemplate.getInterceptors().add((request, body, clientHttpRequestExecution) -> { HttpHeaders headers = request.getHeaders(); if (!headers.containsKey("Authorization")) { String token = bearerToken.toLowerCase().startsWith("bearer") ? bearerToken : "Bearer " + bearerToken; request.getHeaders().add("Authorization", token); } return clientHttpRequestExecution.execute(request, body); }); return restTemplate; } }
quelle