Получение фактических значений параметров в Jersey ResourceFilterFactory

#java #rest #authorization #jersey #jax-rs

#java #остальное #авторизация #джерси #jax-rs

Вопрос:

Я хочу реализовать пользовательскую авторизацию в своих службах REST с использованием Jersey. Эта пользовательская авторизация проверяет аннотации к методам, а также фактические параметры, которые получает метод.

Мой аннотированный метод jax-rs выглядит следующим образом:

 @GET
@Path("customers")
@Requires(Role.CustomerManager)
public Customer getCustomer(@ParseFromQueryString @CheckPermission final Customer customer) {
    // ...
}
  

@ParseFromQueryString Это аннотация, которая указывает Jersey (через вводимого поставщика), чтобы отменить сопоставление a Customer из строки запроса. Код для этого выглядит следующим образом:

 public class QueryStringCustomerInjectable implements Injectable<Customer> {
  public Customer getValue() {
    final Customer customer = new Customer();
    // ... a UriInfo was injected using the @Context annotation
    // ... extract parameters from QueryString and use setters
    return customer;
  }
}
  

@CheckPermission Аннотация указывает моему пользовательскому авторизеру, что разрешения должны быть проверены у клиента. Некоторые пользователи имеют доступ к информации о некоторых клиентах. Аналогично, @Requires аннотация выполняет роль, которую должен выполнять вызывающий. Это не роли безопасности java (строки), скорее, это значения enum.

Используя Jersey ResourceDebuggingFilter в качестве отправной точки, я смог узнать, какой метод будет вызван. Однако я все еще не понял, как определить, какие параметры будут фактически использоваться для вызова метода.

В верхней части моей головы я могу придумать два обходных пути:

  1. Перехватчик методов, использующий Guice Jersey.
  2. Закодируйте эту логику в QueryStringCustomerInjectable , но это кажется немного неаккуратным. Это был бы класс, делающий слишком много.

Тем не менее, я бы действительно хотел сделать это, используя только Jersey / JAX-RS. Я чувствую, что я так близко!

Идеи? Указатели?

Спасибо!

Комментарии:

1. Я все еще не нашел способа сделать это без использования guice… Таким образом, либо используется guice, либо используется cxf, который предоставляет перехватчики и способ предоставления ваших собственных вызывающих устройств.

2. Вы изучали AOP или просто использовали фильтр сервлетов для решения проблемы 1?

3. Вы пробовали использовать ContainerRequestFilter и внедрять в него клиента? Я не уверен, @BeanParam ограничены ли они ресурсами или их также можно вводить в фильтры, но я бы предположил, что пока фильтр не имеет предварительного соответствия, он должен работать.

Ответ №1:

Вы должны использовать Filters or Interceptors для обработки всей информации о методе. смотрите Фильтр Джерси и перехватчики

Ответ №2:

Для десериализации клиента вы могли бы реализовать javax.ws.rs.ext.ParamConverterProvider и зарегистрировать его в Jersey. Затем вы можете внедрить это в свои методы с помощью @QueryParam («клиент»). Это немного более гибко, поскольку вы можете использовать его также с аннотациями @BeanParam или @PathParam.

Затем вы можете использовать ContainerRequestFilter. Смотрите в качестве ссылки, как jersey выполняет Oauth1, например, OAuth1ServerFilter. Следующее, что вы можете сделать, это, возможно, создать функцию, которая будет регистрировать вновь созданный фильтр (см. Oauth1ServerFeature для ссылки — я не смог найти исходный код прямо сейчас).

Удачи!

Ответ №3:

Почему бы не использовать свой собственный фильтр сервлета, например

 public class YourFilter implements Filter {
  ...
  @Override
 public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filterChain) throws IOException, ServletException {

    // HttpServletRequest httpReq = (HttpServletRequest) request;
    // HttpServletResponse httpResp = (HttpServletResponse) response;

    // HttpServletRequest httpReq = (HttpServletRequest) request;
    // HttpServletResponse httpResp = (HttpServletResponse) response;
    // ..... httpReq.getUserPrincipal();


    // then set what you need using ThreadLocal and use it inside your resource class

    // do not forget to call 
    filterChain.doFilter(request, response); // at the end of this method

 }
  

Последний шаг — зарегистрировать ваш фильтр сервлета. Это делается с помощью веб-приложения web.xml

Он перехватит ваши HTTP-запросы до того, как будет вызван фактический код внутри ресурса Джерси.