jersey 2: How to create custom HTTP param binding - java

I am trying to create a custom http param binding for my restful service. Please see the example below.
#POST
#Path("/user/{userId}/orders")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public MyResult foo(#PathParam("userId") String someString, #UserAuthHeaderParam String authString){
}
You can see that there is a UserAuthHeaderParam annotation in the function signature. What I want to do is have a custom http param binding other than the standard javax.ws.rs.*Param .
I have try to implement org.glassfish.hk2.api.InjectionResolver which basically extract the value from http header:
public class ProtoInjectionResolver implements InjectionResolver<UserAuthHeaderParam>{
...
#Override
public Object resolve(Injectee injectee, ServiceHandle< ? > root)
{
return "Hello World";
}
...
}
When I call the restful service, the server get below exceptions. It indicates that the framework fails to resolve the param in the function signature:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String,parent=MyResource,qualifiers={}),position=0,optional=false,self=false,unqualified=null,2136594195),
java.lang.IllegalArgumentException: While attempting to resolve the dependencies of rs.server.MyResource errors were found
Please help. Any advise is appreciated. I do make a lot of search on google but fails to make it work. Jersey 2.*. How to replace InjectableProvider and AbstractHttpContextInjectable of Jersey 1.* might be the similar question.
-- UPDATES:
I use AbstractBinder to bind my resolver to UserAuthHeaderParam:
public class MyApplication extends ResourceConfig
{
public MyApplication()
{
register(new AbstractBinder()
{
#Override
protected void configure()
{
// bindFactory(UrlStringFactory.class).to(String.class);
bind(UrlStringInjectResolver.class).to(new TypeLiteral<InjectionResolver<UrlInject>>()
{
}).in(Singleton.class);
}
});
packages("rs");
}
}
Thank you!

If all you want is to pass value directly from the header to the method you don't need to create custom annotations. Let's say you have a header Authorization, then you can easily access it by declaring your method like this:
#GET
public String authFromHeader(#HeaderParam("Authorization") String authorization) {
return "Header Value: " + authorization + "\n";
}
You can test it by calling curl, e.g.
$ curl --header "Authorization: 1234" http://localhost:8080/rest/resource
Header Value: 1234
Given that the answer to your question, how to create custom binding is as follows.
First you have to declare your annotation like this:
#java.lang.annotation.Target(PARAMETER)
#java.lang.annotation.Retention(RUNTIME)
#java.lang.annotation.Documented
public #interface UserAuthHeaderParam {
}
Having your annotation declared you have to define how it will be resolved. Declare the Value Factory Provider (this is where you'll have access to the header parameters - see my comment):
#Singleton
public class UserAuthHeaderParamValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
protected UserAuthHeaderParamValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator locator) {
super(mpep, locator, Parameter.Source.UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(Parameter parameter) {
Class<?> classType = parameter.getRawType();
if (classType == null || (!classType.equals(String.class))) {
return null;
}
return new AbstractHttpContextValueFactory<String>() {
#Override
protected String get(HttpContext httpContext) {
// you can get the header value here
return "testString";
}
};
}
}
Now declare an injection resolver
public class UserAuthHeaderParamResolver extends ParamInjectionResolver<UserAuthHeaderParam> {
public UserAuthHeaderParamResolver() {
super(UserAuthHeaderParamValueFactoryProvider.class);
}
}
and a Binder for your configuration
public class HeaderParamResolverBinder extends AbstractBinder {
#Override
protected void configure() {
bind(UserAuthHeaderParamValueFactoryProvider.class)
.to(ValueFactoryProvider.class)
.in(Singleton.class);
bind(UserAuthHeaderParamResolver.class)
.to(new TypeLiteral<InjectionResolver<UserAuthHeaderParam>>() {})
.in(Singleton.class);
}
}
now the last thing, in your ResourceConfig add register(new HeaderParamResolverBinder()), like this
#ApplicationPath("rest")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new HeaderParamResolverBinder());
packages("your.packages");
}
}
Given that, you should be now able to use the value as you wanted:
#GET
public String getResult(#UserAuthHeaderParam String param) {
return "RESULT: " + param;
}
I hope this helps.

I don't know how to resolve your exception. However, may I propose you a different way to do the same thing. I hope it helps.
I've faced exactly the same problem: I need extra parameters in the http header (btw, also related to authentication). Besides, I need to send them in every call, since I want to do a "typical" rest implementation, without maintaining a session.
I'm using Jersey 2.7 - but I'd say it should work in 2.0. I've followed their documentation
https://jersey.java.net/documentation/2.0/filters-and-interceptors.html
It's quite clear there, but anyway I copy-paste my implementation below.
It works fine. True there are some other ways to secure a rest service, for example this is a good one:
http://www.objecthunter.net/tinybo/blog/articles/89
But they depend on the application server implementation and the database you use. The filter, in my opinion, is more flexible and easier to implement.
The copy-paste: I've defined a filter for authentication, which applies to every call and it is executed before the service (thanks to #PreMatching).
#PreMatching
public class AuthenticationRequestFilter implements ContainerRequestFilter {
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
if (headers == null) {
throw new...
}
// here I get parameters from the header, via headers.get("parameter_name")
// In particular, I get the profile, which I plan to use as a Jersey role
// then I authenticate
// finally, I inform the Principal and the role in the SecurityContext object, so that I can use #RolesAllowed later
requestContext.setSecurityContext(new SecurityContext() {
#Override
public boolean isUserInRole(final String arg0) {
//...
}
#Override
public boolean isSecure() {
//...
}
#Override
public Principal getUserPrincipal() {
//...
}
#Override
public String getAuthenticationScheme() {
//...
}
});
}
}
You have to include this filter class in your implementation of ResourceConfig,
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
// my init
// my packages
register(AuthenticationRequestFilter.class); // filtro de autenticación
// other register
}
}
Hope it helps!

If your need is to retrieve all the http headers binding into one object, a solution could be to use the #Context annotation to get javax.ws.rs.core.HttpHeaders; which contains the list of all request headers.
#POST
#Path("/user/{userId}/orders")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public MyResult foo(#PathParam("userId") String someString, #Context HttpHeaders headers){
// You can list all available HTTP request headers via following code :
for(String header : headers.getRequestHeaders().keySet()){
System.out.println(header);
}
}

here is my actual implementatipn of UserAuthHeaderParamValueFactoryProvider class
import javax.inject.Inject;
import javax.inject.Singleton;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.server.internal.inject.AbstractValueFactoryProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
import org.glassfish.jersey.server.model.Parameter;
#Singleton
public class UserAuthHeaderParamValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
protected UserAuthHeaderParamValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator locator) {
super(mpep, locator, Parameter.Source.UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(Parameter parameter) {
Class<?> classType = parameter.getRawType();
if (classType == null || (!classType.equals(String.class))) {
return null;
}
return new AbstractContainerRequestValueFactory<String>() {
#Override
public String provide() {
//you can use get any header value.
return getContainerRequest().getHeaderString("Authorization");
}
};
}

Related

Is there a way to get request URI in Spring?

Whenever a request is made, I need to get the request URI for some internal calculations.
For some time I've been doing it like this:
public Mono<Response> example(ServerHttpRequest req) { ... }
And then using req.getURI(), but that becomes a pain once you need to pass it down multiple times. I need the URI object to extract scheme, schemeSpecificPart, host, port from it.
Is there a way to get these properties without extracting them from a request?
UPD: I see that for Web MVC there are convenient methods to retrieve request URI. But I need the same for reactive stack (netty).
It can be achieved by creating WebFilter that puts ServerHttpRequest into the Context:
#Component
#ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class ReactiveRequestContextFilter implements WebFilter {
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
return chain
.filter(exchange)
.contextWrite(ctx -> ctx.put(ReactiveRequestContextHolder.CONTEXT_KEY, request));
}
}
Additionally, create a class that provides static access to request data:
public class ReactiveRequestContextHolder {
public static final Class<ServerHttpRequest> CONTEXT_KEY = ServerHttpRequest.class;
public static Mono<ServerHttpRequest> getRequest() {
return Mono.deferContextual(Mono::just).map(ctx -> ctx.get(CONTEXT_KEY));
}
public static Mono<URI> getURI() {
return getRequest().map(HttpRequest::getURI);
}
}
Methods can be accessed through the class name directly without having to instantiate them. Just be aware that it should not be accessed before the filter is executed.
Example of usage:
#RestController
#RequestMapping
public class TestController {
#GetMapping("/test")
public Mono<URI> test() {
return ReactiveRequestContextHolder.getURI();
}
}
Reference
You can try this :
public Mono<Response> example(WebRequest request){
System.out.println(request.getDescription(false));
.......
}
You can turn this false to true in getDescription as false will only give you the Uri which i think is the only thing you need.
You can inject it in any bean.
#Autowired
private HttpServletRequest request;

Quarkus Annotation-Based Interceptor with Non-Optional Arguments

This seems to be a hot topic based on the amount of questions asked but I have not found the answer I am looking for just yet. I want to implement a simple authorization service in my Quarkus app, but I seem to be repeating code over and over again.
Basically, I take in the JWT from the Authorization Http header and check if the role supplied in it is sufficient to access my endpoint:
public void someApiCall(#Context HttpHeaders headers) {
authService.validate(ApiToken.SOME_API_CALL, headers); // Throws an exception when unauthorized
//…
}
Now, I think this looks really clunky and I do not like the additional parameter that I need for every single Http endpoint. I have done some research into AOP and know how to add an interceptor which could validate the Http headers through an annotation which would be applied to my method:
#Authorize
public void someApiCall(/*…*/) { /*…*/ }
The issue is, I do not know how to pass in arguments into this annotation to specify the required role. I want something like this:
#Authorize(UserRole.SYSADMIN)
This seems pretty simple but I cannot figure it out. Below you will find the interceptor and annotation classes (Missing the required role of course):
Authorize.java
#Retention(value=RUNTIME)
#Target(value=METHOD)
public #interface Authorize {}
AuthorizeInterceptor.java
#Interceptor
#Priority(3000)
#Authorize
public class AuthorizeInterceptor {
#Inject
AuthorizationService authService;
#AroundInvoke
public void validateRole(InvokationContext ctx) {
authService.validate(ApiToken.ALL, ((RestEndpoint)ctx.getTarget()).getHttpHeaders());
}
}
RestEndpoint.java
public class RestEndpoint {
#Context
HttpHeaders headers;
public HttpHeaders getHttpHeaders() { return headers; }
}
SomeResource.java
public class SomeResource extends RestEndpoint {
#GET
#Authorize
public Object someApiCall() {
/* do code directly */
}
}
So, in conclusion, where I write #Authorize, I want to have #Authorize(UserRole.SOME_ROLE).
Thanks in advance!
So, I managed to figure it out. It turns out that it isn't that hard, I just didn't know where to look.
Here are the modified classes:
Authorize.java
#InterceptorBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Authorize {
// Nonbinding is very important. It makes the interceptor fire regardless of the value
#Nonbinding ApiToken value();
}
AuthorizeInterceptor.java
#Interceptor
#Priority(3000)
#Authorize(ApiToken.NULL)
public class AuthorizeInterceptor {
/* fields */
public Object validate(InvokationContext ctx) throws Exception {
authService.validate(/* stays the same */);
return ctx.proceed();
}
}
SomeResource.java
public class SomeResource {
#GET
#Authorize(ApiToken.SOME_API_CALL)
public Object someApiCall() { /* implementation */ }
}
As Turing85 pointed out, a similar API already exists in JavaEE which implements the authorization functionality in the same way.

How do I implement a default functionality for HTTP Method in JAX-RS?

I am using JAX-RS and it has default implementations for #OPTIONS and #HEAD methods, but I would like to provide a different functionality.
What I have done currently is this:
#GET
#Path("path/to/resource")
#Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
// Normal method implementation
}
#OPTIONS
#Path("path/to/resource")
#Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
}
So basically I create a new call to each one of my resources. But I would like to have a catch-all method here that would treat all my calls to #OPTION or to #HEAD.
How do I implement such functionality?
EDIT
Just for clarity. I know how to do this using a Servlet Filter but I am wondering if JAX-RS has a similar feature built-in for th is specific case.
Since you are using Jersey, Jersey has a feature that allows you to programmatically add and modify resources. So you could add OPTIONS and HEAD methods to all your resources, without having to touch your resource classes. Below is an example that does nothing but send a 405 with a No <Method> message. Probably not what you want, but you should be able to figure out what you need to modify to get what you want.
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.process.Inflector;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;
#Provider
public class HeadAndOptionsModelProcessor implements ModelProcessor {
#Override
public ResourceModel processResourceModel(ResourceModel resourceModel,
Configuration configuration) {
ResourceModel.Builder resourceModelBuilder = new ResourceModel.Builder(false);
for (Resource rootResource: resourceModel.getResources()) {
final Resource.Builder rootResourceBuilder = Resource.builder(rootResource);
addOptions(rootResourceBuilder);
addHead(rootResourceBuilder);
for (Resource childResource: rootResource.getChildResources()) {
final Resource.Builder childResourceBuilder = Resource.builder(childResource);
addOptions(childResourceBuilder);
addHead(childResourceBuilder);
rootResourceBuilder.addChildResource(childResourceBuilder.build());
}
resourceModelBuilder.addResource(rootResourceBuilder.build());
}
return resourceModelBuilder.build();
}
#Override
public ResourceModel processSubResource(ResourceModel subResourceModel,
Configuration configuration) {
return subResourceModel;
}
private void addOptions(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("OPTIONS")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
#Override
public Response apply(ContainerRequestContext context) {
return getOptionsResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private void addHead(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("HEAD")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
#Override
public Response apply(ContainerRequestContext context) {
return getHeadResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private static Response getOptionsResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Options").build();
}
private static Response getHeadResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Head").build();
}
}
Default options handler is implemented via
#OPTIONS
#Path("{path: .*}")
public Response allOptions() {
}

JAX-RS #Context usage in Jersey 2 compared to Jersey 1

[EDIT] The problem is with the
register(new ServiceBinder<>(MyService.class));
Jersey generates a warning and ignores the registration for all but the first one (Existing previous registration found for the type); it only considers the type-erased ServiceBinder class to decide there is a conflict.
It looks like I need to use a more sophisticated version of register to get past that issue.
[/EDIT]
In Jersey 1 I was able to use custom injectable providers to inject my objects into both class fields and method parameters, by extending
LazySingletonInjectableProvider
I can't figure out how to port that pattern to Jersey 2 (with hk2 on Tomcat 7). I have read everything I could find on the topic, including Jersey custom method parameter injection with inbuild injection - but I don't want to use a custom annotation, and I am not trying to inject a request parameter.
[EDIT] I made the wrong assumption regarding what works and what doesn't:
Injection into a class field in a ContainerRequestFilter works fine
Injection into a resource, either as class field or method parameter does not work
[EDIT 2]: The InjectionResolver as described below actually doesn't work at all, I have removed it. Jersey already has a ContextInjectionResolver which presumably should take care of the #Context annotation.
I have created and registered an AbstractBinder, and with that class field injection works fine; however method parameter injection doesn't (the binder never gets invoked and the parameter remains null).
I have tried to bind an InjectionResolver but that didn't help either.
Any suggestion on how to make this work would be greatly appreciated... here is the current code:
The HK2 binder:
public class ServiceBinder<T> extends AbstractBinder
{
private final Factory<T> _factory;
private final Class<? extends T> _clazz;
public OsgiServiceBinder(Class<T> clazz)
{
_factory = new ServiceFactory<>(clazz);
_clazz = clazz;
}
protected void configure()
{
bindFactory(_factory).to(_clazz); //.in(RequestScoped.class);
bind(ServiceInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<Context>>() { })
.in(PerLookup.class);
}
}
The injection resolver:
public class ServiceInjectionResolver<T> implements InjectionResolver<Context>
{
private Class<T> _clazz;
public OsgiServiceInjectionResolver(Class<T> clazz)
{
_clazz = clazz;
}
public Object resolve(Injectee injectee, ServiceHandle<?> root)
{
if (_clazz.getCanonicalName().equals(injectee.getRequiredType().getTypeName())) {
return Framework.getService(_clazz);
}
return null;
}
public boolean isConstructorParameterIndicator()
{
return false;
}
public boolean isMethodParameterIndicator()
{
return true;
}
}
The JAX-RS registration:
public class MyApplication extends Application
{
public MyApplication()
{
registerClasses(<resource classes>);
register(new ServiceBinder<>(MyService.class));
}
}
The resource class:
#Path("/schedules")
public class SchedulesResource
{
#Context UriInfo _uriInfo;
// This injection works fine, _service1 is properly initialized
#Context MyService _service1;
#PUT
#Consumes({MediaType.APPLICATION_JSON})
#Path("{jobGroup}/{jobName}")
public Response putSchedule(#Context MyService service2,
...)
{
// The injection of service2 doesn't work...
}
}
The Factory class:
public class ServiceFactory<T> implements Factory<T>
{
private Class<T> _clazz;
protected ServiceFactory(Class<T> clazz)
{
_clazz = clazz;
}
public T provide()
{
return Framework.getService(_clazz);
}
}
public void dispose(T t)
{
}
}
pok
The problem was actually with Jersey component registrations.
Even though I was registering binder instances, Jersey was checking the class (ServiceBinder) and discarding all but the first registration (WARN: existing registration found for the type).
This seems a bit bogus given I am registering instances, and I wish Jersey would fail with an error rather than log a warning when failing to register a component, but the solution is to simply change the registration pattern slightly:
// Doesn't work
register(new ServiceBinder<>(MyService1.class));
register(new ServiceBinder<>(MyService2.class));
// Works like a charm
register(new ServiceBinder(MyService1.class, MyService2.class));
where obviously the ServiceBinder is adjusted to call bindFactory for each supplied service.

Jax-RS - Custom attribute to get header value

EDIT: I just realized, is it even possible to perform a custom action with a custom attribute in Java? Or is it just informational?
I want to include an authentication token in my Jax-RS service header, but I don't want to add a parameter to every request to get the header and check it like so:
public Response getUser(#Context HttpHeaders headers) {
if(authorize(headers.getRequestHeader("token").get(0)) {
// Do something
}
}
I would much rather add an attribute to each request (or even the class if that is possible:
#Authorize
public Response getUser() {
// Do something
}
This way I can also add the attribute to only the requests I want to.
And if the request isn't authorized, I can override it and return a 401.
A custom attribute is easy to write, but how can I get the header information in the attribute without passing it in every time?
NOTE: I would rather not use a web.xml. I don't have one right now and I don't like using them. I want to keep my code clean without xml and I think if I used a filter/web.xml it would apply to all calls. If that is the only way, I will, but I much prefer the approach with custom attributes.
"I think if I used a filter/web.xml it would apply to all calls"
Actually there are #NameBinding annotations we can use. For example
#NameBinding
#Rentention(RetentionPoilicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface Authorize {}
Then just annotate the filter and the methods/classes you want filtered.
#Authorize
public Response getUser() {
// Do something
}
#Provider
#Authorize
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
MultivauledMap<String, String> headers - requestContext.getHeaders();
...
if (!authorized) {
throw new NotAuthorizedException();
}
}
}
Notice the use of #Priority. This is important. Say you want the authenticate also, so you create a filter for authentication. If you don't set the priority, either filter may occur first. It's unpredictable. If we provide the authentication filter with #Priority(Priorities.AUTHENTICATION), then that filter will always occur before the #Priority(Priorities.AUTHORIZATION) filter.
You will also need to register this filter with the Application subclass (See some other Deployment Options (Jersey, but the Application subclass is portable with implementations))
#ApplicationPath("/api")
public class YourApplication extends Application {
private Set<Class<?>> classes = new HashSet<>();
private Set<Object> singletons = new HashSet<>();
public YourApplication() {
classes.add(AuthorizationRequestFilter.class);
}
#Override
public Set<Class<?>> getClasses() {
return classes;
}
#Override
public Set<Object> singletons() {
return singletons;
}
}
See more on Filters and Interceptors
See the WebAppplicationException Hierarchy for more exceptions like NotAuthorizedException
See the Priorities class and Priories guide
The best way to solve your use case would be to use name binding and filters. In this way, you can use a filter to do your authorization logic as well as return a 401 in the case of unauthorized requests.
You can find more information here.
Name binding via annotations is only supported as part of the Server API. In name binding, a name-binding annotation is first defined using the #NameBinding meta-annotation:
#Target({ ElementType.TYPE, ElementType.METHOD })
#Retention(value = RetentionPolicy.RUNTIME)
#NameBinding
public #interface Logged { }
The defined name-binding annotation is then used to decorate a filter or interceptor class (more than one filter or interceptor may be decorated with the same name-binding annotation):
#Logged
public class LoggingFilter
implements ContainerRequestFilter, ContainerResponseFilter {
...
}
At last, the name-binding annotation is applied to the resource method(s) to which the name-bound JAX-RS provider(s) should be bound to:
#Path("/")
public class MyResourceClass {
#GET
#Produces("text/plain")
#Path("{name}")
#Logged
public String hello(#PathParam("name") String name) {
return "Hello " + name;
}
}
A name-binding annotation may also be attached to a custom JAX-RS Application subclass. In such case a name-bound JAX-RS provider bound by the annotation will be applied to all resource and sub-resource methods in the JAX-RS application:
#Logged
#ApplicationPath("myApp")
public class MyApplication extends javax.ws.rs.core.Application {
...
}
Based on peeskillet's answer, which the concept is right but the code is slightly wrong, this is the final code for the answer.
Using #NameBinding, this works:
Authorize.java
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface Authorize {
}
AuthorizeFilter.java
note: still needs to do the actual token authorization. This is just checking if the token exists right now.
#Provider
#Authorize
#Priority(Priorities.AUTHORIZATION)
public class AuthorizeFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
MultivaluedMap<String, String> headers = requestContext.getHeaders();
String token = headers.getFirst("token");
if (token == null || token.isEmpty()) {
Response.ResponseBuilder responseBuilder = Response
.status(Response.Status.UNAUTHORIZED)
.type(MediaType.APPLICATION_JSON)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600");
requestContext.abortWith(responseBuilder.build());
}
}
}
ApplicationConfig.java
note: add the filter here so it doesn't have to be included in the web.xml
#ApplicationScoped
#ApplicationPath("/api")
public class ApplicationConfig extends Application
{
#Override
public Set<Class<?>> getClasses()
{
return getRestResourceClasses();
}
private Set<Class<?>> getRestResourceClasses()
{
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(com.example.AuthorizeFilter.class);
resources.add(com.example.UserService.class);
return resources;
}
}

Categories

Resources