java - Jersey - 将过滤器中的变量作为 RequestScoped 注入(inject)

标签 java jersey jersey-2.0

我想在调用我的资源方法之前在过滤器中执行身份验证。在此过滤器中,我还想检索用户的权限并通过 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 ContainerRequestContext 来查找角色。您只需在身份验证过滤器内创建 SecurityContext ,以便下一个过滤器可以查找它。

你可以看一个例子here 。您可以在isUserInRole中检查用户权限。当设置SecurityContext时,Jersey的过滤器将被调用,它会调用你的isUserInRole。通过这种方式,您可以免费获得访问控制。

关于java - Jersey - 将过滤器中的变量作为 RequestScoped 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32073948/

相关文章:

java - 如何在 testng extent-report 版本 2.41.2(相关代码)中添加数据提供者值

java - 在子类的构造函数中使用构建器模式

java - Android - 源端口 800 的 DatagramSocket 不发送

java - 在 List<List<Entry<String, Double>>> 中使用 Java 8 过滤对象排列

java - 通过 Jersey 服务器中的超时对 Java 方法实现 QoS 指标

java - REST:客户端可以通过 POST 传递包装对象吗?

javax.ws.rs.core.Response.readEntity() 陷入无限循环

java - 在 WildFly 8.1 上运行 Jersey2 REST 客户端时出现问题

java - JerseyServlet 在服务器启动时初始化资源

java - Jersey 远程 IP 地址无法正常工作