我已经实施了一个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());
}
}
}
如你所见,我更新了SecurityContext
请求的,将其设置为我自己的自定义实现的实例(JwtSecurityContext
) 如果验证成功。此实现添加了额外的身份验证和授权数据,我希望稍后在后续过滤器和资源方法中访问这些数据。
我还实施了一个AuthorizationFilter
在之后立即调用AuthenticationFilter
。在这里,我可以访问更新的JwtSecurityContext
正好。
但是,当我尝试注入时遇到问题JwtSecurityContext
到资源(方法)中。
我目前正在使用 Jersey,并且我在其文档中阅读了以下内容 https://jersey.java.net/documentation/latest/security.html#d0e12280:
The SecurityContext
可以直接从中检索ContainerRequestContext
via 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'
}
}
正如注释所示,运行时类型securityContext
变量变为SecurityContextInjectee
。通过调试,我发现这包含了ContainerRequest
这反过来又包裹了我的JwtSecurityContext
。但是,没有吸气剂,而且我不想使用反射来深入了解这个对象层次结构,所以我不知道如何掌握我的JwtSecurityContext
.
我尝试过改变@Context SecurityContext securityContext
to @Context JwtSecurityContext jwtSecurityContext
,但如果我这样做,变量就会变成null
。我也尝试过字段注入,但其行为是相同的。
我是否走错了路?我是否应该访问我的自定义SecurityContext
在我的资源方法中?一种替代方法是将我的所有数据包装在Principal
我返回的实现getUserPrincipal
in my JwtSecurityContext
。我想代理(SecurityContextInjectee
) 会将调用转发给其底层JwtSecurityContext
因此归还我的Principal
,但我不确定,最终我更愿意使用我的JwtSecurityContext
而不是将这些值包装在Principal
执行。