JAX-RS 2.0 Filter parameters via @NameBinding anno

2019-03-25 07:36发布

I've created some JAX-RS 2.0 resources (using Jeresey 2.4 running in a Servlet container) and a filter that handles authentication and authorisation that can be selectively applied via a @NameBinding annotation. This all works great.

I would like to be able to define some parameters on this annotation (specifically, security permissions that are required to access each method/resource) that can be available to the filter at runtime to alter this behaviour.

I notice that interceptors can do this via javax.ws.rs.ext.InterceptorContext.getAnnotations() but there is no equivalent in javax.ws.rs.container.ContainerRequestContext for filters. Any ideas how this may be achieved? I would like to be able to do something like the following:

@Target({TYPE, METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@NameBinding
public @interface Secured {
    String[] requiredPermissions() default {};
}

@Secured
@Priority(Priorities.AUTHENTICATION)
public class SecurityRequestFilter implements ContainerRequestFilter {
    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {
        // extract credentials, verify them and check that the user has required permissions, aborting if not
    }
}

@Path("/userConfiguration/")
public class UserConfigurationResource {
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Secured(requiredPermissions = {"configuration-permission"})
    public Response getConfig(@Context HttpServletRequest httpServletRequest) {
        // produce a response
    }
}

2条回答
【Aperson】
2楼-- · 2019-03-25 08:17

You can get this information from UriInfo, particularly it's (Jersey specific) ExtendedUriInfo subinterface. To obtain an instance either invoke ContainerRequestContext#getUriInfo() and cast it

final ExtendedUriInfo extendendUriInfo = (ExtendedUriInfo) containerRequestContext.getUriInfo();

or inject it into your filter:

@Inject
private ExtendedUriInfo extendendUriInfo;

then

extendedUriInfo
    .getMatchedResourceMethod()
    .getInvocable()
    .getHandlingMethod().getAnnotation(Secured.class);

In the second approach you can implement DynamicFeature and assign your filter only to a particular resource methods (i.e. in case the configuration of the filter is more complex, filter applies only to a couple of methods and you want to reduce the overhead, ...). Take a look at the implementation of RolesAllowedDynamicFeature which adds support for security annotations over resource methods in Jersey.

查看更多
何必那么认真
3楼-- · 2019-03-25 08:24

For a non-vendor specific solution, since JAX-RS 2.0 you can use ResourceInfo:

@Secured
@Priority(Priorities.AUTHENTICATION)
public class SecurityRequestFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        Method method = resourceInfo.getResourceMethod();

        if (method != null) {
            Secured secured = method.getAnnotation(Secured.class);
            ...
        }
    }
}
查看更多
登录 后发表回答