JAX-RS:自定义 SecurityContext 在注入资源方法时具有意外类型
JAX-RS: Custom SecurityContext has unexpected type when injected into resource method
我已经实现了一个 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,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
注入资源方法,如下所示:
@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
吗?一种替代方法是将我的所有数据包装在 Principal
实现中,我 return 来自 getUserPrincipal
在我的 JwtSecurityContext
中。我想代理 (SecurityContextInjectee
) 会将调用转发到其基础 JwtSecurityContext
,因此 return 我的 Principal
,但我不确定,最终我更愿意使用我的 JwtSecurityContext
而不是将这些值包装在 Principal
实现中。
您可以注入 ContainerRequestContext
(如 this post 中所述)并从那里获取 SecurityContext
。
public List<SomeItem> getItems(@Context ContainerRequestContext context) {
JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext();
}
我已经实现了一个 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,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
注入资源方法,如下所示:
@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
吗?一种替代方法是将我的所有数据包装在 Principal
实现中,我 return 来自 getUserPrincipal
在我的 JwtSecurityContext
中。我想代理 (SecurityContextInjectee
) 会将调用转发到其基础 JwtSecurityContext
,因此 return 我的 Principal
,但我不确定,最终我更愿意使用我的 JwtSecurityContext
而不是将这些值包装在 Principal
实现中。
您可以注入 ContainerRequestContext
(如 this post 中所述)并从那里获取 SecurityContext
。
public List<SomeItem> getItems(@Context ContainerRequestContext context) {
JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext();
}