Jax-RS - Custom attribute to get header value

authentication, java, jax-rs

Solution

"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

Problem

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.

Original source

Related problems