我正在使用jersey 2.17和HK2创建一个简单的rest应用。我有一个ContainerRequestFilter拒绝任何没有“ currentuser” cookie的请求。
ContainerRequestFilter
我有这样的事情:
@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真的很陌生,并且真的很难找到方法。
我只是在要求正确的接口来实现(或扩展类)。
您要找的不是一件容易的事。解决此问题的一种方法是在SecurityContext内部设置ContainerRequestFilter,如此处所示。这不涉及与HK2的任何直接交互。然后,您可以将注入到SecurityContext资源类中。并吸引用户
SecurityContext
securityContext.getUserPrincipal().getName();
如果你真的想要去一个自定义注释注入的用户名,您将需要创建一个InjectionResolver(请参阅定义定制注塑注释。你可以注入ContainerRequestContext(同一个,传递给在过滤法ContainerRequestFilter)或SecurityContext到InjectionResolver。例如
InjectionResolver
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")); } }
注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface CurrentUser { }
注入解析器
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则将为null。似乎ContainerRequestContext还没有我们设置的属性,这意味着似乎正在发生的是InjectResolver在过滤器之前调用。我将需要对此进行调查。使其成为预赛者,不需要IMO。
@PreMatching
User
InjectResolver
不过,就我个人而言,我会采用第一种方法,只是使用SecurityContext。我上面提供的链接中有一个完整的示例。通过这种方法,您可以根据需要利用Jersey的优势RolesAllowedDynamicFeature。
RolesAllowedDynamicFeature