2015-05-04 5 views
2

Я работаю с jersey 2.17 и HK2 для создания простого приложения для отдыха. У меня есть ContainerRequestFilter, который отклоняет любой запрос, у которого нет файла cookie currentuser.Джерси и HK2 - текущий пользователь

У меня есть что-то вроде этого:

@Path("/users") 
public class UserResource { 

     private UserService userService; 

     @GET 
     @Path("/orders") 
     @Produces("application/json") 
     public List<Order> findOrdersOfCurrentUser() { 
      // some ugly code to access headers, extract cookies, and finally 
      // extract username (a String) from a particular cookie 

      return this.userService.findOrdersByUsername(username) ; 
     } 
} 

Я хочу, чтобы закодировать что-то более изящное, чем это. Как это:

@Path("/users") 
public class UserResource { 

      private UserService userService; 

      @CurrentUsername 
      private String currentUser; 

      @GET 
      @Path("/orders") 
      @Produces("application/json") 
      public List<Order> findOrdersOfCurrentUser() { 
       return this.userService.findOrdersByUsername(username) ; 
      } 
    } 

Я действительно новичок в HK2 и становится очень трудно найти способ сделать это.

Я просто прошу о правильном интерфейсе для реализации (или расширения класса).

ответ

4

То, что вы ищете, не является тривиально выполненным. Один из способов справиться с этим - установить SecurityContext внутри ContainerRequestFilter, как seen here. Это не предполагает прямого взаимодействия с HK2. Затем вы можете ввести SecurityContext в свой класс ресурсов. И заставить пользователь по

securityContext.getUserPrincipal().getName(); 

Если вы действительно хотите идти с инъекционным именем пользователя с помощью пользовательской аннотации, вам нужно будет создать InjectionResolver (See Defining Custom Injection Annotation. Вы можете придать ContainerRequestContext (тот же один передаются метода фильтра в ContainerRequestFilter) или SecurityContext в InjectionResolver. Например

Фильтр

@Provider 
@PreMatching 
public class UserFilter implements ContainerRequestFilter { 

    public static final String USER_PROP = "user"; 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     requestContext.setProperty(USER_PROP, new User("peeskillet")); 
    } 
} 

Реферат

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface CurrentUser { 
} 

InjectionResolver

public class CurrentUserInjectionResolver implements InjectionResolver<CurrentUser> { 

    javax.inject.Provider<ContainerRequestContext> requestContext; 

    @Inject 
    public CurrentUserInjectionResolver(
     javax.inject.Provider<ContainerRequestContext> requestContext) { 
     this.requestContext = requestContext; 
    } 

    @Override 
    public Object resolve(Injectee injectee, ServiceHandle<?> sh) { 
     if (User.class == injectee.getRequiredType()) { 
      return requestContext.get().getProperty(UserFilter.USER_PROP); 
     } 
     return null; 
    } 

    @Override 
    public boolean isConstructorParameterIndicator() { return false; } 

    @Override 
    public boolean isMethodParameterIndicator() { return false; } 
} 

Свяжите InjectionResolver

@Provider 
public class UserFeature implements Feature { 

    @Override 
    public boolean configure(FeatureContext context) { 
     context.register(new AbstractBinder(){ 
      @Override 
      public void configure() { 

       bind(CurrentUserInjectionResolver.class) 
       .to(new TypeLiteral<InjectionResolver<CurrentUser>>(){}) 
         .in(Singleton.class); 
      } 
     }); 
     return true;   
    } 
} 

Ресурс

@Path("user") 
public class UserResource { 

    @CurrentUser 
    private User user; 

    @GET 
    public Response getCurrentUser() { 
     return Response.ok(user.getUsername()).build(); 
    } 
} 

Теперь я не совсем уверен, что этот второй подход, по крайней мере, часть о фильтр является фильтром @PreMatching. Если я не сделаю его предварительным сопоставлением, то User будет пустым. Кажется, что ContainerRequestContext еще не имеет свойства, которое мы устанавливаем, то есть то, что, по-видимому, происходит, - это вызов InjectResolver перед фильтром. Мне нужно будет изучить это. Сделав это предварительным согласованием, ИМО не требуется.

Лично я бы пошел с первым подходом, просто используя SecurityContext. Полный пример приведен в приведенной выше ссылке. При таком подходе вы можете воспользоваться Джерси RolesAllowedDynamicFeature, если это необходимо.

+0

это было здорово! работал как шарм – justatester

+0

на самом деле он работает только для инъекций на основе полей и конструкторов. он не работает для инъекций, основанных на методе, и не на основе параметров. – justatester

+0

http://stackoverflow.com/a/30426226/2587435 –