JAX-RS:自定义SecurityContext在注入资源方法时具有意外类型

Jan*_*ken 3 java authentication authorization jax-rs jersey

我已经实现了一个ContainerRequestFilter执行基于JWT的身份验证:

@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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我还实现了一个AuthorizationFilter在之后立即调用的AuthenticationFilter.在这里,我可以访问更新JwtSecurityContext就好了.

但是,当我尝试将JwtSecurityContext资源注入资源(方法)时,我遇到了问题.

我目前正在使用Jersey,我在其文档中阅读了以下内容:

SecurityContext可以从直接检索 ContainerRequestContext经由getSecurityContext()方法.您还可以SecurityContext使用该setSecurityContext(SecurityContext)方法将请求上下文中的默认值替换为自定义上下文中的默认值.如果在您的设置中设置自定义SecurityContext实例ContainerRequestFilter,则此安全上下文实例将用于注入JAX-RS资源类字段.这样,您就可以实现自定义身份验证筛选器,可以设置自己的身份验证筛选器SecurityContext.要确保提前执行自定义身份验证请求筛选器,请使用常量将筛选器优先级设置为AUTHENTICATION Priorities.早期执行身份验证筛选器将确保所有其他筛选器,资源,资源方法和子资源定位器将与您的自定义SecurityContext实例一起执行 .

我尝试将这样注入JwtSecurityContext资源方法:

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

正如注释所示,securityContext变量的运行时类型变为SecurityContextInjectee.从调试开始,我发现它包裹了一个ContainerRequest反过来包裹我的JwtSecurityContext.但是,没有getter,我不想使用反射来深入挖掘这个对象层次结构,所以我不知道如何抓住我的JwtSecurityContext.

我试图改变@Context SecurityContext securityContext@Context JwtSecurityContext jwtSecurityContext,但如果我这样做,变变null.我也尝试过野外注射,但这种行为方式相同.

我走错了路吗?我不应该SecurityContext在我的资源方法中访问我的自定义吗?一种替代方法是将我的所有数据包装在Principal我从getUserPrincipal我的实现中返回的实现中JwtSecurityContext.我想proxy(SecurityContextInjectee)会将调用转发给它的底层JwtSecurityContext因此返回我的Principal,但我不确定,最后我宁愿使用my JwtSecurityContext而不是在Principal实现中包装这些值.

Pau*_*tha 6

您可以注入ContainerRequestContext(如中提到的这篇文章),只是得到了SecurityContext从那里.

public List<SomeItem> getItems(@Context ContainerRequestContext context) {
    JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext();
}
Run Code Online (Sandbox Code Playgroud)