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

标签 java authentication jersey authorization jax-rs

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

@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 注入(inject)资源(方法)时遇到问题。

我目前正在使用 Jersey,并且 I've read the following in its documentation :

The SecurityContext can be directly retrieved from ContainerRequestContext via getSecurityContext() method. You can also replace the default SecurityContext in a request context with a custom one using the setSecurityContext(SecurityContext) method. If you set a custom SecurityContext instance in your ContainerRequestFilter, this security context instance will be used for injection into JAX-RS resource class fields. This way you can implement a custom authentication filter that may setup your own SecurityContext to be used. To ensure the early execution of your custom authentication request filter, set the filter priority to AUTHENTICATION using constants from Priorities. An early execution of you authentication filter will ensure that all other filters, resources, resource methods and sub-resource locators will execute with your custom SecurityContext instance.

我尝试将 JwtSecurityContext 注入(inject)资源方法,如下所示:

@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。我也尝试过字段注入(inject),但它的行为方式相同。

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

最佳答案

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

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

关于java - JAX-RS:自定义 SecurityContext 在注入(inject)资源方法时具有意外类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39487860/

相关文章:

java - 在 Fragments 中使用 JSON 时,应用程序在 Android 开发中没有响应

Java:写入 Scala 输出流

ruby-on-rails - Rails devise 求助路由报错 No route matches "/sessions/user"

json - Jersey 客户端 POST 结果 - header full : java. lang.RuntimeException: Header>6144

tomcat - Jersey - 不扫描资源?

java - 使用 java.text.NumberFormat 解析日本货币字符串

java - 将对象从flex发送到java servlet

php - 如何在 zf2 中使用户名不区分大小写

authentication - 将 IdentityServer 4 与 ASP.NET Core Identity 一起使用的附加值(value)是什么?

java - Jersey 不遵循 302 重定向