java - Jersey y HK2-usuario actual de inyección
dependency-injection jersey-2.0 (1)
Estoy trabajando con jersey 2.17 y HK2 para crear una aplicación de descanso simple. Tengo un ContainerRequestFilter
que rechaza cualquier solicitud que no tenga la cookie "usuario actual".
Tengo algo como esto:
@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) ;
}
}
Quiero codificar algo más elegante que eso. Me gusta esto:
@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) ;
}
}
Soy muy nuevo en hk2 y me resulta muy difícil encontrar la manera de hacerlo.
Solo estoy pidiendo la interfaz correcta para implementar (o clase para ampliar).
Lo que estás buscando no se hace trivialmente. Una forma de manejar esto es establecer el SecurityContext
dentro de ContainerRequestFilter
, como se ve aquí . Esto no implica ninguna interacción directa con HK2. A continuación, puede inyectar SecurityContext
en su clase de recursos. Y obtener el usuario por
securityContext.getUserPrincipal().getName();
Si realmente desea agregar el nombre de usuario con una anotación personalizada, deberá crear un InjectionResolver
( consulte Definición de la anotación de inyección personalizada . Puede inyectar ContainerRequestContext
(el mismo que pasó al método de filtro en el ContainerRequestFilter
) o el SecurityContext
en el InjectionResolver
. Por ejemplo
Filtrar
@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"));
}
}
Anotación
@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; }
}
Enlace el 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;
}
}
Recurso
@Path("user")
public class UserResource {
@CurrentUser
private User user;
@GET
public Response getCurrentUser() {
return Response.ok(user.getUsername()).build();
}
}
Ahora no estoy seguro de este segundo enfoque, al menos la parte sobre el filtro es un filtro @PreMatching
. Si no hago una pre-coincidencia, el User
será nulo. Parece que ContainerRequestContext
aún no tiene la propiedad que establecimos, lo que significa que lo que parece estar sucediendo es que se llama a InjectResolver
antes del filtro. Tendré que investigar esto. Haciéndolo una pre-coincidencia, IMO no debería ser requerido.
Personalmente, me gustaría ir con el primer enfoque, simplemente usando el SecurityContext
. Un ejemplo completo está en el enlace que proporcioné arriba. Con este enfoque, puede aprovechar la RolesAllowedDynamicFeature
de Jersey si es necesario.