2016-09-14 105 views
1

我实现了一个ContainerRequestFilter进行基于JWT认证意想不到类型:JAX-RS:自定义的SecurityContext有当注入资源的方法

@Provider 
@Priority(Priorities.AUTHENTICATION) 
public class AuthenticationFilter implements ContainerRequestFilter { 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     AuthenticationResult authResult = ... 
     if (authResult.isSuccessful()) { 
      // Client successfully authenticated. 
      // Now update the security context to be the augmented security context that contains information read from the JWT. 
      requestContext.setSecurityContext(new JwtSecurityContect(...)); 
     } else { 
      // Client provided no or an invalid authentication token. 
      // Deny request by sending a 401 response. 
      requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); 
     } 
    } 
} 

正如你所看到的,我更新请求SecurityContext,设置如果验证成功,它将成为我自己的自定义实现(JwtSecurityContext)的一个实例。此实现添加额外的身份验证和授权数据,我希望稍后在我的后续过滤器和我的资源方法中访问这些数据。

我也实施了AuthorizationFilter,在AuthenticationFilter后立即调用。在这里,我可以访问更新的JwtSecurityContext就好了。

但是,我在尝试将JwtSecurityContext注入资源(方法)时遇到了问题。我目前使用泽西

,和I've read the following in its documentation

SecurityContext可以直接从 ContainerRequestContext经由getSecurityContext()方法检索。您也可以使用setSecurityContext(SecurityContext)方法,在请求上下文中用 替换请求上下文中的默认SecurityContext,替换为 。如果您在ContainerRequestFilter中设置了 定制SecurityContext实例,则将使用此 安全上下文实例注入JAX-RS 资源类字段。通过这种方式,您可以实施自定义 认证过滤器,该认证过滤器可以将您自己的SecurityContext设置为 。为确保您的自定义验证 请求过滤器的早期执行,请使用来自Priorities的 常量将过滤器优先级设置为AUTHENTICATION。早期执行您的身份验证 过滤器将确保所有其他过滤器,资源,资源方法 和子资源定位器将与您的定制 SecurityContext实例一起执行。

我尝试了JwtSecurityContext注入资源的方法,像这样:

@Path("/somepath") 
public class SomeResource { 
    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<SomeItem> getItems(@Context SecurityContext securityContext) { 
     // securityContext is of type 'SecurityContextInjectee' 
    } 
} 

正如评论指出,该securityContext变量的运行时类型变得SecurityContextInjectee。从调试中,我发现这包装了ContainerRequest,后者又包装了我的JwtSecurityContext。但是,没有getter,并且我不想使用反射来深入查看此对象层次结构,因此我不知道如何获取我的JwtSecurityContext

我已经尝试将@Context SecurityContext securityContext更改为@Context JwtSecurityContext jwtSecurityContext,但是如果我这样做,变量将变为null。我也尝试过野外注射,但这种行为方式相同。

我正走向一条错误的道路吗?我应该在我的资源方法中访问我的自定义SecurityContext吗?一种替代方案可能是将我的所有数据都包含在我的JwtSecurityContext中从getUserPrincipal返回的Principal实现中。我想代理(SecurityContextInjectee)会将呼叫转移到其底层的JwtSecurityContext,因此返回我的Principal,但我不确定,最终我宁愿使用我的JwtSecurityContext,而不是将这些值包装在Principal实现中。

+0

@peeskillet有趣的是,我不知道我可以注入ContainerRequestContext。我想我将能够调用getSecurityContext并返回我的自定义安全上下文。 –

+0

@peeskillet是的,注入ContainerRequestContext并在该实例上调用getSecurityContext确实会返回JwtSecurityContext。谢谢!如果你愿意,你可以把它作为答案发布,我会接受它。 –

回答

3

您可以注入ContainerRequestContext(如this post中所述),并从那里获取SecurityContext

public List<SomeItem> getItems(@Context ContainerRequestContext context) { 
    JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext(); 
} 
+0

谢谢。顺便说一句,你碰巧知道关于JPA的一两件事吗?我仍然在寻找这个问题的答案:http://stackoverflow.com/questions/38664913/jpa-locking-when-performing-an-indirect-insertion –

+0

我知道一些JPA,但它不是我每天使用的东西。我认为这个问题稍微先进一点,我的知识:-( –

+0

好吧,只是认为它会给它一个镜头:)。再次感谢! –

相关问题