2015-05-04 55 views
2

我正在與球衣2.17和HK2一起創建一個簡單的休息應用程序。 我有一個ContainerRequestFilter拒絕任何沒有「currentuser」cookie的請求。澤西島和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(); 

得到用戶如果你真的想要去一個自定義註釋注入的用戶名,您將需要創建一個InjectionResolverSee Defining Custom Injection Annotation。你可以注入ContainerRequestContext(同一個傳遞給過濾方法在例如

過濾

@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")); 
    } 
} 

註釋

ContainerRequestFilter)或 SecurityContextInjectionResolver
@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。我需要看看這個。使之成爲預先匹配,IMO不應被要求。

個人而言,我會用第一種方法,只使用SecurityContext。一個完整的例子在我上面提供的鏈接中。採用這種方法,您可以根據需要利用澤西島的RolesAllowedDynamicFeature

+0

太棒了!像一個魅力 – justatester

+0

工作實際上它只適用於基於場和基於構造函數的注入。它不適用於基於方法的注入或基於參數的注入。 – justatester

+0

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