Adding authentication to outbound http requests - spring

I have a rest web service that is implemented using spring boot starter web. This service acts as a client to another application that requires authentication to make calls to it.
Calls made from the client to the server are using org.springframework.web.client.RestTemplate.
Is there a way to come up with a solution to add authentication headers to outbound requests at one single point before they are sent out?
I don't want to add headers in each of the requests separately.

Javadoc for RestTemplate says:
This template uses a SimpleClientHttpRequestFactory and a
DefaultResponseErrorHandler as default strategies for creating HTTP
connections or handling HTTP errors, respectively. These defaults can
be overridden through
HttpAccessor.setRequestFactory(org.springframework.http.client.ClientHttpRequestFactory)
So I would take SimpleClientHttpRequestFactory and override its prepareConnection(..) method.

Related

Is it possible to disable Spring Cloud Sleuth header propagation based on destination URL?

We're using Brave's ExtraFieldPropagation feature to propagate custom fields (e.g. an internal-only request identifier) between services as HTTP headers.
Some of our services make requests to external services using a RestTemplate or Feign client in the course of processing a request. Since Sleuth enhances all RestTemplate beans and Feign clients with the propagation feature, this means that external services receive the internal-only headers, which I'd like to avoid.
I know of two workarounds that allow me to avoid this behavior, both of which are flawed:
Instantiate a client object manually as opposed to using a #Bean so that Sleuth does not add an interceptor. The downside I see here is that developers have to remember to follow this pattern to avoid leaking information, and this is difficult to enforce.
Add an interceptor that removes these headers from outgoing requests. The downsides here are that a) I need separate interceptors for RestTemplate and Feign clients (not a huge deal); b) it looks like Feign client interceptors do not have a way to influence order of execution (see javadoc here), so I can't guarantee that the new interceptor will run last / after the Sleuth one.
Is there a way to customize Sleuth (e.g. via some kind of injector bean) such that, prior to injecting headers in an outgoing HTTP request, I can reason about the destination of the request? I saw documentation regarding custom injector beans, but it appears those no longer exist in spring boot >= 2. I can't seem to find an equivalent construct in Brave.
You can unsample a given URL which means that the headers will be propagated but not sent to Zipkin. You can't disable instrumentation for only some of the URLs cause we're instrumenting all of the components that are registered as beans.

Spring RestTemplate netflix loadblancer not configuring httpClient header Host

We have a complicated app based on Spring Cloud, Netflix Loadbalancer, to make calls between micro-services ms1<client>-->ms2<server>
We are using a restTemplate.exchange call to a URI hostname that is a Eureka Key for FQDN lookup.
This configuration works in other micro-services, in fact the the restTemplate bean works for a different component's micro-service call.
The receiving the rest call is Cloud Foundry Go-router which I believe is just a ngineX proxy server, the httpClient request should have the header variable set to "Host":"FQDN" this allows the proxy to route the request to the proper instance in the space.
PROBLEM:
httpClient from ms makes the call to the ms
CompletionException. cause: org.springframework.web.client.HttpClientErrorException: 404 NOT_FOUND
This is the response from the CF go-router (simple proxy server), the request never gets http--> the ms instance.
When the RestClient configures the request it sets the header "Host" as localhost:8090 or whatever the ms hostname is???
Discussion related Questions:
So apparently we have a configuration problem here.
Any advice on how the netflix ribbon loadbalancer client stuff sets the httpClient headers?
What package class interceptor does this magic?
What configuration variables effect this?
Code debugging indicates that netflix.client.SimpleVipAddressResolver is running.
We've traced the debug all the way to the Apache httpClient and it has the header Host set to the ms hostname, it's set to that value in the netflix httpClient wrapper too.
I tried to create a simple reference implementation of this, but can't.
Any recommendations on troubleshooting?
Where to look or read docs on what com.netflix package?
Using the Camden Spring. Using profiles,
From the memory debugging;
ClientClassName:com.netflix.niws.client.http.RestClient
VipAddressResolverClassName:com.netflix.client.SimpleVipAddressResolver
NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
NFLoadBalancerClassName:com.netflix.loadbalancer.ZoneAwareLoadBalancer
NFLoadBalancerRuleClassName:com.netflix.loadbalancer.AvailabilityFilteringRule
EnablePrimeConnections:false,
CustomSSLSocketFactoryClassName:null,
TrustStorePassword:null,
EnableConnectionPool:true,
listOfServers:,
OkToRetryOnAllOperations:false,
RequestIdHeaderName:null
Our suspicion is that some application.properties, .yml, or bootstrap.yml is being set or not being set some where in the scan path ???.
We had just upgrade the platform spring boot 1.3.x to 1.4.2.
The ms inbound controller had the annotation
#RequestHeader HttpHeaders httpHeaders
Which is what we attached into the restTemplate.execute as a parameter and eventually found it way to the rest-netflix-httpClient as the request headers being used to call the ms. The Go-Router on CF must be using that value to perform the proxying to the instance.
Apparently, somewhere in the upgrades, one of two things happen, either
A) boot Controller #RequestHeader in version 1.3.2 did not put header Host.
B) previous versions of spring Cloud-netflix-ribbon overwrote the Host httpHeader value with the Ribbon lookup.
Either way, there was no special interceptor.
Spring cloud netflix Eureka will take whatever httpHeaders you provide (even if that header is key:Host and use those values.

How to access request object in #MessageMapping method with spring websocket implementation

I am integrating an existing spring MVC web application with spring websockets. I was successfully able to integrate by following the instructions in
https://spring.io/guides/gs/messaging-stomp-websocket/
The existing web application has a filter, which sets a few of the attributes. I have a requirement to access the attributes set by the filter in the controller i,e in #MessageMapping method.
Could some one tel how can we access the request object in the #MessageMapping method?
When a STOMP client connects to the application, it first has to request a protocol upgrade to switch to websocket. Once using that websocket connection, the messages sent/received don't go through your regular Servlet filter - only the first HTTP request (the "Handshake") did.
Depending on your use case, there are several ways to achieve this.
If it's related to Authentication, then there are existing features for this in the Spring Framework, but also in Spring Security.
If it's related to the HTTP session, you can easily ask for all HTTP session attributes to be copied into the websocket session - or even customize the Handshake for your own needs (see reference doc). Once done, you can inject the Websocket scope in a #MessageMapping controller method and get those attributes (see reference doc).

Spring Integration - HTTP gateway and JMS

I have a requirement where client sends an HTTP requests, our application processes it and generates response and sends back the HTTP response. The request and response need to be persisted on JMS queues. In order for us to leverage Spring integration in this scenario, can we use spring integration HTTP gateways in place of our current MVC controllers ? Would I need separate gateways for each different uri mapping ? Can the HTTP gateway be integrated with JMS channels ? I would appreciate some ideas on the high level architecture using Spring Integration for this scenario.
Thanks.
The fastest on-ramp would probably to inject a Messaging Gateway (<gateway/>) into your existing controller; if you are simply archiving the request/response, you just need a simply gateway method that returns void and in the Spring Integration flow, wire the <gateway/> to a <jms:outbound-channel-adapter/>.

Spring add header to Outgoing requests

I want to add a Authorization header to all outgoing requests of my Spring 3.2 application.
This solution describes how to do it by adding an interceptor to a web service template (e.g. RestTemplate):
Setting a custom HTTP header dynamically with Spring-WS client
Is there a way to do it without adding interceptors to my restTemplates? Globally, for all outgoing request?

Resources