我想在调用资源方法之前在过滤器中执行身份验证。在此过滤器中,我还想检索用户的权限并通过RequestScoped @Inject注释传递它。
@Authenticated
public class AuthenticationFilter implements ContainerRequestFilter {
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Authenticated {};
@Inject
private ISecurityHandler handler;
public AuthenticationFilter() {}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Filter out unauthorized
// Retrieve user permissions
this.handler.setUserPermissions(...);
}
}
资源:
@Path("my-path")
public class GetVisitorsDataResource {
@Inject private ISecurityHandler handler;
@GET
@Path("resource-method")
@Authenticated
@Produces(MediaType.APPLICATION_JSON)
public Response resource() {
System.out.println(handler.getUserPermissions());
return Response.ok().build();
}
}
我已注册过滤器和注射工厂。
public static class SecurityHandlerProvider implements Factory<ISecurityHandler> {
@Override
public ISecurityHandler provide() {
System.out.println("PROVIDING SECURITY CONTEXT!");
return new SecurityHandlerImpl();
}
@Override
public void dispose(ISecurityHandler instance) {
System.out.println("DISPOSING SECURITY CONTEXT!");
}
}
我也受了约束。
bindFactory(SecurityHandlerProvider.class).to(ISecurityHandler.class).in(RequestScoped.class);
在收到请求并且只能在该请求中访问时,创建对象非常重要。请求完成后,应调用dispose方法。我可以通过@Singleton注释实现类似功能的唯一方法。但是,请求完成后对象不会被销毁,并且会在所有请求中共享。
我已经花了太多时间研究这个问题,是否有人知道如何实现首选结果?
答案 0 :(得分:3)
您的代码并没有多大意义。您注入ISecurityHandler
的另一个地方和另一个地点SecurityHandler
,但工厂适用于ISecurityContext
。我将假设这些是拼写错误或复制和粘贴错误。
除此之外我还假设一切都没问题,因为你说它可以作为单身人士使用。因此,我猜测您正面临&#34;不在请求范围内&#34; 错误。最简单的解决方法是使用javax.inject.Provider
注入,这允许我们懒惰地检索对象。检索对象时,它将包含请求范围。
@Inject
private javax.inject.Provider<ISecurityContext> securityContextProvider;
@Override
public void filter(ContainerRequestContext context) throws IOException {
ISecurityContext sc = securityContextProvider.get();
}
...
bindFactory(SecurityHandlerProvider.class)
.to(ISecurityContext.class)
.in(RequestScoped.class);
注意,您还应确保使用AuthenticationFilter
对@Priority(Priorities.AUTHENTICATION)
进行注释,以便它在任何其他过滤器之前发生,即使您更喜欢它是@PreMatching
过滤器。我认为,在系统越早进行身份验证之前,就越好。
顺便说一句,你可能想看看泽西岛的RolesAllowedDynamicFeature
。它允许您使用jsr250注释@RolesAllowed
,@DenyAll
和@PermitAll
作为资源类和方法。
它基本上是在Priorites.AUTHENTICATION
过滤器之后发生的过滤器,它会从javax.ws.rs.core.SecurityContext
查找ContainerRequestContext
以查找角色。您只需在身份验证过滤器中创建SecurityContext
,以便下一个过滤器可以查找它。
您可以看到示例here。您可以在isUserInRole
中查看用户权限。设置SecurityContext
后,系统会调用泽西过滤器,然后调用isUserInRole
。这样做,您可以免费获得访问控制。