Jersey 2 - ContainerRequestFilter get method annotation

☆樱花仙子☆ 提交于 2020-01-06 02:46:08

问题


Im trying to get the Method annotation in ContainerRequestFilter object.

Controler:

@GET
@RolesAllowed("ADMIN")
public String message() {
    return "Hello, rest12!";
}

ContainerRequestFilter :

@Provider
public class SecurityInterceptor implements  javax.ws.rs.container.ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) {
//Here I need To get the @RolesAllowed("ADMIN") annotation value
}

Application :

@ApplicationPath("/rest")
public class ExpertApp extends Application {
private final HashSet<Object> singletons = new LinkedHashSet<Object>();

public ExpertApp() {
    singletons.add(new SecurityInterceptor());
}   

@Override
public Set<Object> getSingletons() {
    return singletons;
}

public Set<Class<?>> getClasses() {
    return new HashSet<Class<?>>(Arrays.asList(UserControler.class, SearchController.class));

}

}

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<!-- Servlet declaration can be omitted in which case it would be automatically 
    added by Jersey -->
<servlet>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>

<servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

How do I ge the @RolesAllowed("ADMIN") value,


回答1:


You could...

Inject into your filter @Context ResourceInfo, as seen here, and get the annotation from the Method

RolesAllowed annot = resourceInfo.getResourceMethod().getAnnotation(RolesAllowed.class);

But...

Jersey already has a RolesAllowedDynamicFeature that implements the access control for the annotations @RolesAllowed, @PermitAll and @DenyAll. You just need to register the feature with your application

In ResourceConfig

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        super(MyResource.class);
        register(RolesAllowedDynamicFeature.class);
    }
}

In web.xml

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature
    </param-value>
</init-param>

Or in your Application subclass, you can add it to your getSingletons() or getClasses() set. Doesn't make much difference which one. No injections occur, so it would be safe to just instantiate it and add it to the singletons.

Note: The first option can be done in any JAX-RS 2.0 application, while the second is Jersey specific.




回答2:


Your ContainerRequestFilter is implemented as post-matching filters. It means that the filters would be applied only after a suitable resource method has been selected to process the actual request i.e. after request matching happens.

So, @RolesAllowed("ADMIN") will block the call and your filter will never be called.

To avoid that issue, I create custom annotation; for instance:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyRoles {
    public enum MyRole {
        USER, OFFICER, COMPLIANCE, ADMIN
    }

    MyRole role() default MyRole.USER;

    Class<? extends Throwable> expected() default None.class;

    static class None extends Throwable {

        /**
             * 
             */
        private static final long serialVersionUID = 1L;
    }
}

In my webservice, I can annotate the method:

@POST
@MyRoles
@Path("/secured")
@Produces("application/json")
@Consumes("application/json")
public String mySecuredMethod() {
    // This method is annotated with @MyRoles
    // The authentication filter will be executed before invoking this
    // method
    return "{message='secured'}";
}

And in the filter, I check for the custom annotation:

private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final String AUTHENTICATION_SCHEME = "Basic";
private static final ServerResponse BAD_REQUEST = new ServerResponse("Token invalid or expired", 400, new Headers<Object>());;
private static final ServerResponse ACCESS_DENIED = new ServerResponse("Access denied for this resource", 401, new Headers<Object>());;
private static final ServerResponse ACCESS_FORBIDDEN = new ServerResponse("Nobody can access this resource", 403, new Headers<Object>());;
private static final ServerResponse SERVER_ERROR = new ServerResponse("INTERNAL SERVER ERROR", 500, new Headers<Object>());;

@Override
public void filter(ContainerRequestContext requestContext) {
    System.err.println("GFA Debug SecurityInterceptor ............ ");
    System.err.println(requestContext.getUriInfo().getRequestUri());

    Method method = resourceInfo.getResourceMethod();
    System.out.println("GFA DEbug method.getName() " + method.getName());

    System.out.println("GFA DEbug method.isAnnotationPresent(PermitAll.class) = " + method.isAnnotationPresent(PermitAll.class));

    // Access denied for all
    if (method.isAnnotationPresent(DenyAll.class)) {
        requestContext.abortWith(ACCESS_FORBIDDEN);
        return;
    }

    // Access allowed for all
    if (method.isAnnotationPresent(PermitAll.class)) {
        System.out.println("GFA debug permitAll ... bye");
        return;
    }

    // Custom roles
    System.out.println("GFA Debug method.isAnnotationPresent(MyRole.class) = " + method.isAnnotationPresent(MyRoles.class));
    if (!method.isAnnotationPresent(MyRoles.class)) {
        requestContext.abortWith(ACCESS_FORBIDDEN);
        return;
    }

    MyRoles myannotation = method.getAnnotation(MyRoles.class);
    System.out.println("GFA custom role ... " + myannotation.role());

    // Then I check for token and validity of role, etc.
}


来源:https://stackoverflow.com/questions/31974857/jersey-2-containerrequestfilter-get-method-annotation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!