泽西岛 - 从过滤器中注入变量作为RequestScoped

时间:2015-08-18 13:34:23

标签: 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();
    }
}

我已注册过滤器和注射工厂。

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注释实现类似功能的唯一方法。但是,请求完成后对象不会被销毁,并且会在所有请求中共享。

我已经花了太多时间研究这个问题,是否有人知道如何实现首选结果?

1 个答案:

答案 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。这样做,您可以免费获得访问控制。