4

In Jersey 1.x we accessed the Wicket session from a (Jersey) session attribute, as described here https://stackoverflow.com/a/15767824/1399659.

In moving to Jersey 2.x it seems the proper pattern to use a ContainerRequestFilter, which also allows Spring bean injection as well. We have this working successfully by including

<param-name>jersey.config.server.provider.packages</param-name>

as an init-param to the ServletContainer and using the @Provider annotation on a ContainerRequestFilter implementation. But this container filter is a singleton, and it's not possible to inject the HttpServletRequest into this (see JERSEY-2114)

In the filter() method we have access to the ContainerRequestContext but can't access the HttpServletRequest from there.

So is there a way to either:

  1. Enable Spring bean injection within a servlet filter (with Jersey too)?
  2. Access the servlet request from within a ContainerRequestFilter?
  3. Access wicket session from Spring-bean-aware object with Jersey filtering ability some other way?

`

import java.io.IOException;

import javax.servlet.http.HttpSession;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;

import org.apache.wicket.injection.Injector;

@Provider
public class SecurityContextFilter implements ContainerRequestFilter {

//@Context
//HttpServletRequest webRequest;

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
    //HttpSession httpSession = webRequest.getSession();
    //MyWicketSession mySession = (MyWicketSession) httpSession.getAttribute("wicket:" + BaseConstants.WICKET_FILTER_NAME + ":session");
    //doAuthCheck(mySession, requestContext);
}
...
}

`

Thanks in advance

Community
  • 1
  • 1
Brad M
  • 405
  • 6
  • 17

1 Answers1

10

Fixed in Jersey 2.4:

import javax.annotation.Priority;
import javax.ws.rs.Priorities;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthRequestFilter implements ContainerRequestFilter {
    @Context
    HttpServletRequest webRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        final HttpSession session = webRequest.getSession();

        requestContext.setSecurityContext(new SecurityContext() {
            @Override
            public Principal getUserPrincipal() {
                return new PrincipalImpl((String)session.getAttribute("USER_NAME"));
            }

            @Override
            public boolean isUserInRole(String s) {
                return false;
            }

            @Override
            public boolean isSecure() {
                return false;
            }

            @Override
            public String getAuthenticationScheme() {
                return null;
            }
        });
    }
}

You can also register the filter without using @Provider annotation:

import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;

/**
 * Root REST resource class.
 */
@ApplicationPath("/rest")
public class RootResource  extends ResourceConfig {
    /**
     * Initializes all resources from REST package.
     */
    public RootResource() {
        packages("com.example.rest");
        register(AuthRequestFilter.class);
    }
}

Note: Glassfish 4.0.0 uses old Jersey 2.0. You will have to upgrade Jersey using these tips (it's not proven to work well). Or the better way is to download nightly build of Glassfish 4.0.1. but it's not completely stable at the moment. I hope the new version will be released soon.

Viacheslav Dobromyslov
  • 3,168
  • 1
  • 33
  • 45
  • Works a treat, thanks! Others can note too, that if can't use `@Provider` etc annotations due to lack of support for `jersey.config.server.provider.packages` init-param (eg in WebSphere), then the same can be achieved by passing an instance of your provider class back in `getSingletons()` in your implementation of `javax.ws.rs.core.Application` – Brad M Nov 18 '13 at 03:37
  • Or extend ResourceConfig and register the filter there. – Viacheslav Dobromyslov Nov 19 '13 at 04:18
  • My `ContainerRequestFilter` is created once during application startup, so when my `filter` method is invoked, the `HttpServletRequest` doesn't get injected. Any idea what I'm doing wrong? – aioobe Aug 24 '15 at 17:26
  • When filter is registered as a provider, Jersey is trying to inject @Context attributes and fails because it happens outside of a request chain. How to register a filter without be a provider? – Singagirl Oct 14 '15 at 05:35
  • I actually upgraded Jersey as instructed and kept getting nulls for the request... it is only then that I stumbled at https://github.com/dropwizard/dropwizard/issues/1630 that nailed the problem... it's all about the registration of your filter... if you register an instance rather than a class then the injection will fail – GBa Jan 06 '18 at 13:17