我实现了一个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
实现中。
@peeskillet有趣的是,我不知道我可以注入ContainerRequestContext。我想我将能够调用getSecurityContext并返回我的自定义安全上下文。 –
@peeskillet是的,注入ContainerRequestContext并在该实例上调用getSecurityContext确实会返回JwtSecurityContext。谢谢!如果你愿意,你可以把它作为答案发布,我会接受它。 –