简体   繁体   中英

Adding authorization header to Jersey SSE Client request

I am using Jersey client to connect to an SSE stream. The server requires that I add a header to the http request for authorization, but I can't figure out how to add the header.

Here is my code:

Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
WebTarget target = client.target(baseurl + "/v1/devices/events/");
eventSource = EventSource.target(target).build();
eventSource.register(getEventListener());
eventSource.open();

Here is an example of the header I need to add:

Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55

It would be something like this for Basic Authentication:

Client client = ClientBuilder.newClient();
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().build();
client.register(feature);
client.register(SseFeature.class);
WebTarget target = client.target(baseurl + "/v1/devices/events/")
    .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "...")
    .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "...");

...

You already get the password encoded by Jersey.

And if it is a token:

Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseurl + "/v1/devices/events/")
    .request("...")     
    .header(HttpHeaders.AUTHORIZATION, "Bearer " + "... encoded token ...");

Hope it helps!

// Using SSL + Header Key 
uri = UriBuilder.fromUri(sslUrl).port(sslServerPort).build();
sslConfig = SslConfigurator.newInstance().trustStoreFile(trustStoreFile).trustStorePassword(trustStorePassword);
sslContext = sslConfig.createSSLContext();
client = ClientBuilder.newBuilder().sslContext(sslContext).build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);


// Using UserName & Password + Header Key 
uri = UriBuilder.fromUri(url).port(serverPort).build();
basicAuth = HttpAuthenticationFeature.basic(username, userPassword);
client = ClientBuilder.newBuilder().register(basicAuth).build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);

// Using only Header Key 
uri = UriBuilder.fromUri(url).port(serverPort).build();
client = ClientBuilder.newBuilder().build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);

Hope this helps you with your problem.

In case someone would want to add the bearer token header at the Client entity level itself, rather than at the Request entity level (in my case I had a factory method for returning preconfigured Client entities, so I had no way of adding the authorization header within the factory method, as .header(...) becomes available only after you go through the ClientBuilder.newBuilder().register(...).build().target(...).request(...) call chain, as of Jersey 2.x):

// client is a javax.ws.rs.client.Client entity
Feature feature = OAuth2ClientSupport.feature("YOUR_BEARER_TOKEN");
client.register(feature);
// now you can use client.target(...).request(...).post(...), without calling .header(...) after .request(...)

Unfortunately (as you may have guessed) this requires a new dependency: org.glassfish.jersey.security:oauth2-client

<dependency>
  <groupId>org.glassfish.jersey.security</groupId>
  <artifactId>oauth2-client</artifactId>
  <version>2.15</version>
</dependency>

试试这个:

Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, "Bearer38bb7b318cc6898c80317decb34525844bc9db55");

I realize this question is a year old but since there are not a lot to be found on that subject, I'll share my solution.

Based on suggested OAuth2Feature, I came up with this solution:

  1. Create a custom feature. Feature will reference a custom filter
  2. Create a custom filter of priority HEADER_DECORATOR
  3. Create a HeaderProvider interface. Provider will be passed to the filter
  4. Register the WebClient with the custom feature

Header provider interface

@FunctionalInterface
public interface ISseHeaderProvider {
    Map<String, String> getHeaders();  
} 

Custom feature

public class SseHeaderSupportFeature implements Feature {
    private final SseHeaderSupportFilter filter;


    public SseHeaderSupportFeature(ISseHeaderProvider provider) {
        this.filter = new SseHeaderSupportFilter(provider);
    }

    @Override
    public boolean configure(FeatureContext context) {
        context.register(filter);
        return true;
    }
}

Custom filter

@Priority(Priorities.HEADER_DECORATOR)
public class SseHeaderSupportFilter  implements ClientRequestFilter {

    private final ISseHeaderProvider provider;

    public SseHeaderSupportFilter(@NotNull ISseHeaderProvider provider) {
        this.provider = provider;
    }


    @Override
    public void filter(ClientRequestContext request) throws IOException {
        provider.getHeaders().forEach((k, v) -> request.getHeaders().add(k, v));
    }
}

Usage

ISseHeaderProvider provider = () -> MapBuilder.<String, String>builder().add("Authorization", "Bearer ...").build(); 
Client client = ClientBuilder.newBuilder()
                             .register(SseFeature.class)
                             .register(new SseHeaderSupportFeature(provider))
                             .build();
WebTarget target = client.target(UriBuilder.fromPath(getUrl()));
//EventSource eventSource = ....

This solution is generic and allows you to easily add an Authorization header without having to add another dependency.

Following answer is useful: Server Sent Event Client with additional Cookie It use a customized WebTarget to add cookie and the same way on header also work.

public class AuthorizationHeaderWebTarget implements WebTarget {

    private WebTarget base;

    private String token;

    public AuthorizationHeaderWebTarget(WebTarget base, String token) {
        this.base = base;
        this.token = token;
    }

    // Inject that cookie whenever someone requests a Builder (like EventSource does):
    public Invocation.Builder request() {
        return base.request().header(HttpHeaders.AUTHORIZATION, token);
    }

    public Invocation.Builder request(String... paramArrayOfString) {
        return base.request(paramArrayOfString).header(HttpHeaders.AUTHORIZATION, token);
    }

    public Invocation.Builder request(MediaType... paramArrayOfMediaType) {
        return base.request(paramArrayOfMediaType).header(HttpHeaders.AUTHORIZATION, token);
    }

    public Configuration getConfiguration() {
        return base.getConfiguration();
    }

    //All other methods from WebTarget are delegated as-is:

    public URI getUri() {
        return base.getUri();
    }

    public UriBuilder getUriBuilder() {
        return base.getUriBuilder();
    }

    public WebTarget path(String paramString) {
        return base.path(paramString);
    }

    public WebTarget matrixParam(String paramString, Object... paramArrayOfObject) {
        return base.matrixParam(paramString, paramArrayOfObject);
    }

    public WebTarget property(String paramString, Object paramObject) {
        return base.property(paramString, paramObject);
    }

    public WebTarget queryParam(String paramString, Object... paramArrayOfObject) {
        return base.queryParam(paramString, paramArrayOfObject);
    }

    public WebTarget register(Class<?> paramClass, Class<?>... paramArrayOfClass) {
        return base.register(paramClass, paramArrayOfClass);
    }

    public WebTarget register(Class<?> paramClass, int paramInt) {
        return base.register(paramClass, paramInt);
    }

    public WebTarget register(Class<?> paramClass, Map<Class<?>, Integer> paramMap) {
        return base.register(paramClass, paramMap);
    }

    public WebTarget register(Class<?> paramClass) {
        return base.register(paramClass);
    }

    public WebTarget register(Object paramObject, Class<?>... paramArrayOfClass) {
        return base.register(paramObject, paramArrayOfClass);
    }

    public WebTarget register(Object paramObject, int paramInt) {
        return base.register(paramObject, paramInt);
    }

    public WebTarget register(Object paramObject, Map<Class<?>, Integer> paramMap) {
        return base.register(paramObject, paramMap);
    }

    public WebTarget register(Object paramObject) {
        return base.register(paramObject);
    }

    public WebTarget resolveTemplate(String paramString, Object paramObject) {
        return base.resolveTemplate(paramString, paramObject);
    }

    public WebTarget resolveTemplate(String paramString, Object paramObject, boolean paramBoolean) {
        return base.resolveTemplate(paramString, paramObject, paramBoolean);
    }

    public WebTarget resolveTemplateFromEncoded(String paramString, Object paramObject) {
        return base.resolveTemplateFromEncoded(paramString, paramObject);
    }

    public WebTarget resolveTemplates(Map<String, Object> paramMap) {
        return base.resolveTemplates(paramMap);
    }

    public WebTarget resolveTemplates(Map<String, Object> paramMap, boolean paramBoolean) {
        return base.resolveTemplates(paramMap, paramBoolean);
    }

    public WebTarget resolveTemplatesFromEncoded(Map<String, Object> paramMap) {
        return base.resolveTemplatesFromEncoded(paramMap);
    }

}

Following is the code to use it:

EventSource eventSource = new EventSource(new AuthorizationHeaderWebTarget(target, token));
eventSource.register(new EventListener() {
       public void onEvent(final InboundEvent inboundEvent) {
               //...
       }
});

Here is the complete examples

 ClientConfig clientConfig = new ClientConfig(); Client client = ClientBuilder.newClient(clientConfig); WebTarget webTarget = client.target("http://localhost:8080/MyApp/customer/"); Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, "your secret key"); response = invocationBuilder.get(); output = response.readEntity(String.class); 

Dependency for jersey client

 <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>2.25.1</version> </dependency> 

If you use jercy client using header in websource

Client client=Client.create();          
WebResource webresource=client.resource(urlLink);
ClientResponse clientResponse=webresource.header("authorization", accessToken)
    .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM