Параметры фильтра JAX-RS 2.0 с помощью аннотации @NameBinding

Я создал некоторые ресурсы JAX-RS 2.0 (используя Jeresey 2.4, работающий в контейнере Servlet), и фильтр, который обрабатывает аутентификацию и авторизацию, которые могут быть выборочно применены с помощью аннотации @NameBinding. Все это отлично работает.

Я хотел бы иметь возможность определять некоторые параметры этой аннотации (в частности, разрешения безопасности, необходимые для доступа к каждому методу/ресурсу), которые могут быть доступны фильтру во время выполнения, чтобы изменить это поведение.

Я заметил, что перехватчики могут сделать это через javax.ws.rs.ext.InterceptorContext.getAnnotations(), но нет эквивалента в javax.ws.rs.container.ContainerRequestContext для фильтров. Любые идеи, как это может быть достигнуто? Я хотел бы иметь возможность сделать что-то вроде следующего:

@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
    }
}

Ответ 1

Для конкретного решения, отличного от поставщика, поскольку JAX-RS 2.0 вы можете использовать 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);
            ...
        }
    }
}

Ответ 2

Вы можете получить эту информацию из UriInfo, особенно это (особенно Джерси) ExtendedUriInfo. Чтобы получить экземпляр, вызовите ContainerRequestContext # getUriInfo() и произнесите его

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

или введите его в свой фильтр:

@Inject
private ExtendedUriInfo extendendUriInfo;

затем

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

Во втором подходе вы можете реализовать DynamicFeature и назначить свой фильтр только определенным ресурсным методам (т.е. в случае, если конфигурация фильтр более сложный, фильтр применяется только к нескольким методам, и вы хотите уменьшить накладные расходы,...). Взгляните на реализацию RolesAllowedDynamicFeature, в котором добавлена ​​поддержка аннотаций безопасности над методами ресурсов в Джерси.