我已经实现了一个执行基于 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 fromContainerRequestContext
viagetSecurityContext()
method. You can also replace the defaultSecurityContext
in a request context with a custom one using thesetSecurityContext(SecurityContext)
method. If you set a customSecurityContext
instance in yourContainerRequestFilter
, 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 ownSecurityContext
to be used. To ensure the early execution of your custom authentication request filter, set the filter priority to AUTHENTICATION using constants fromPriorities
. An early execution of you authentication filter will ensure that all other filters, resources, resource methods and sub-resource locators will execute with your customSecurityContext
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/