0

An application I work on exposes various REST Web Services with the following pattern:

@RequestScoped
@Path("/path")
public class SomeResource {

    @GET
    public SomeResponse get(
        @HeaderParam("authenticationHeader1") String authenticationHeader1,
        @HeaderParam("authenticationHeader2") String authenticationHeader2,

        @QueryParam("stuff") String stuff, 
        @QueryParam("moreStuff") String moreStuff)      
    {
        final AuthenticationBean authBean = validateCredentials(authenticationHeader1, authenticationHeader2)

        if (!authBean.isValid()) {
            return someStronglyWordedResponse(authBean);
        }
        else { 
            return someProcessing(authBean, stuff, moreStuff);
        }
    }

Parsing, validation, and other handling of these authentication headers is done for nearly all resources.

I could make an abstract superclass and simply define validateCredentials() there, as the AuthenticationBean extraction is the same everywhere.

But this strikes me as moderately inelegant in this Java EE7 context, and more important, what if Jimmy forgets to add authentication management when coding a new resource?

Is there a recommended way to parse the HTTP headers of all requests no matter the target resource, and do some generic processing with the results?

Edit:

This app is using Resteasy. Sorry for not mentioning it in the first place. I would prefer to avoid implementation-dependent solutions, but Resteasy mechanisms are also an option.

Silver Quettier
  • 2,045
  • 2
  • 26
  • 53
  • 1
    All the APIs mentioned in the duplicate link's accepted answer are standard JAX-RS classes. Will work for whatever implementation. – Paul Samsotha Jun 13 '16 at 06:48
  • @peeskillet Indeed! Sorry for my quick reopen edit then, I was mislead by the duplicate question title. Perhaps it could be edited to remove the Jersey reference? That's what made me skip the question in the first place. – Silver Quettier Jun 13 '16 at 07:29

1 Answers1

0

Jersey provides a ContainerRequestFilter for this. They have a nice tutorial on how to use them here: https://jersey.java.net/documentation/latest/filters-and-interceptors.html

You can just create a global filter and in there do your validation, and if it fails you can abort it with requestContext.abortWith(), as shown in Example 10.2. This example can easily be modified to use your header data instead of a security context. The headers can be accessed using requestContext.getHeaderString() with the header name as the only parameter.

You can also use Name binding (10.5 in the tutorial) to only filter requests for certain resources.

Leon
  • 2,926
  • 1
  • 25
  • 34
  • Thank you for your answer @Leon. Sadly, the app uses Resteasy and not Jersey, so I won't be able to use this... However, I'll keep your solution in mind if we ever switch implementation. – Silver Quettier Jun 13 '16 at 06:22
  • @SilverQuettier The filters and interceptors mentioned in the Jersey link are standard JAX-RS classes. Will work with whatever implementation – Paul Samsotha Jun 13 '16 at 06:50