Java jersey 2.6:ContainerRequestFilter:不在请求范围内

时间:2016-12-19 11:28:00

标签: java rest tomcat jersey

我在tomcat上有一个服务休息,它正常工作但是当我在另一个tomcat服务器上部署它时,它会引发异常。

我正在尝试实现ContainerRequestFilter。此异常似乎是由我的authenticationFilter(实现ContainerRequestFilter的类)中的@Context resourceInfo引起的。但我不明白为什么以及如何解决它。 (我跟着this tutorial)

A MultiException has 3 exceptions.  They are:
1. java.lang.IllegalStateException: Not inside a request scope.
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of services.AuthentificationFilter errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on services.AuthentificationFilter

org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:270)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:414)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456)
org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:114)
org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:102)
org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:153)
org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2445)
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:98)
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
org.glassfish.jersey.internal.inject.Providers.getAllRankedProviders(Providers.java:234)
org.glassfish.jersey.server.ApplicationHandler.getProcessingProviders(ApplicationHandler.java:616)
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:409)
org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:161)
org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:286)
org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:283)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:298)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:745)

我的authenticationFilter的代码

@Provider
public class AuthentificationFilter implements javax.ws.rs.container.ContainerRequestFilter {

@Context
private ResourceInfo resourceInfo;

private static final String AUTHORIZATION = "Authorization";
private static final String BASIC = "Basic";
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("Essayez de mettre sudo devant votre requete").build();
private static final Response ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN).entity("You shall not pass !").build();

@Override
public void filter(final ContainerRequestContext context) throws IOException {
    Method method = resourceInfo.getResourceMethod();
    if(!method.isAnnotationPresent(PermitAll.class)) {
        MultivaluedMap<String, String> headers = context.getHeaders();
        List<String> authorization = headers.get(AUTHORIZATION);

        if(method.isAnnotationPresent(DenyAll.class)) {
            context.abortWith(ACCESS_FORBIDDEN);
            return;
        }else if(authorization == null || authorization.isEmpty()) {
            context.abortWith(ACCESS_DENIED);
            return;
        }

        String encodedUserPassword = authorization.get(0).replaceFirst(BASIC + " ", "");
        String auth = new String(Base64.getDecoder().decode(encodedUserPassword.getBytes()));;

        String[] authTab = auth.split(":");
        String username = authTab[0];
        String password = authTab[1];

        if(method.isAnnotationPresent(RolesAllowed.class)) {
            RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
            Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
            if(!isAllowed(username, password, rolesSet)) {
                context.abortWith(ACCESS_DENIED);
                return;
            }
        }
    }
}

private boolean isAllowed(final String username, final String password, final Set<String> rolesSet)
{
    boolean isAllowed = false;
    User user;
    if((user = new UserMapper().get(username, password)) != null) {
        String role = user.getStatus().toString();
        if(rolesSet.contains(role))
            isAllowed = true;
    }
    return isAllowed;
}

}

注册过滤器的MyApplication.java代码:

public class MyApplication extends ResourceConfig {

public MyApplication() {
    packages("services");
    register(AuthentificationFilter.class);
}
}

最后是web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">

<servlet>
    <servlet-name>Example API</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>services.MyApplication</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Example API</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

我做错了什么?

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方案。我必须创建一个实现DynamicFeature的类,并通过自定义构造函数注册我的AuthenticationFilter。

@Provider
public class AuthenticationDynamicFeature implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
        featureContext.register(new AuthenticationFilter(resourceInfo));
    }
}

这里是自定义构造函数:

public AuthenticationFilter(ResourceInfo resourceInfo) {
    super();
    this.resourceInfo = resourceInfo;
}

我尝试了很多其他方法,而这一方面,它是唯一一个适合我的方式。