我想在调用我的资源方法之前在过滤器中执行身份验证。在此过滤器中,我还想检索用户的权限并通过 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();
}
}
我已经注册了过滤器和用于注入(inject)的工厂。
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!");
}
}
我也绑定(bind)了。
bindFactory(SecurityHandlerProvider.class).to(ISecurityHandler.class).in(RequestScoped.class);
重要的是,该对象是在收到请求时创建的,并且只能在该请求内访问。当请求完成时,应该调用 dispose 方法。我实现类似目标的唯一方法是通过 @Singleton 注释。但是,该对象在请求完成后不会被销毁,而是在所有请求之间共享。
我已经在这个问题上投入了太多时间,也许有人知道如何实现首选结果?
最佳答案
你的代码并没有多大意义。您在一个地方注入(inject) ISecurityHandler
,另一个地方注入(inject) SecurityHandler
,但工厂是针对 ISecurityContext
的。我只会假设这些是拼写错误或复制粘贴错误。
除此之外,我假设一切都很好,因为你说它可以作为单例工作。所以我猜您正面临“不在请求范围内”错误。最简单的解决方法是使用 javax.inject.Provider
进行注入(inject),这允许我们延迟检索对象。当对象被检索时,它将在请求范围内。
@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);
注意,您还应该确保使用 @Priority(Priorities.AUTHENTICATION)
注释您的 AuthenticationFilter
,以便它出现在任何其他过滤器之前,即使您更喜欢它是一个 @PreMatching 过滤器。我想说,身份验证越早进入系统越好。
顺便说一句,您可能想查看 Jersey 的 RolesAllowedDynamicFeature
。它允许您对资源类和方法使用 jsr250 注释 @RolesAllowed
、@DenyAll
和 @PermitAll
。
它基本上是一个在 Priorites.AUTHENTICATION
过滤器之后发生的过滤器,它从 中查找
来查找角色。您只需在身份验证过滤器内创建 javax.ws.rs.core.SecurityContext
ContainerRequestContextSecurityContext
,以便下一个过滤器可以查找它。
你可以看一个例子here 。您可以在isUserInRole
中检查用户权限。当设置SecurityContext
时,Jersey的过滤器将被调用,它会调用你的isUserInRole
。通过这种方式,您可以免费获得访问控制。
关于java - Jersey - 将过滤器中的变量作为 RequestScoped 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32073948/