JAX-RS:自定义SecurityContext在注入资源方法

时间:2016-09-14 10:12:24

标签: java authentication jersey authorization jax-rs

我已经实现了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

  

可以直接从中检索SecurityContext   ContainerRequestContext通过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。但是,没有getter,我不想使用反射来深入挖掘这个对象层次结构,所以我不知道如何抓住我的@Context SecurityContext securityContext

我尝试将@Context JwtSecurityContext jwtSecurityContext更改为null,但如果我这样做,则变量变为SecurityContext。我也尝试过野外注射,但这种行为方式相同。

我走错了路吗?我是否应该在资源方法中访问自定义Principal?一种替代方法是将我的所有数据包含在getUserPrincipal中,JwtSecurityContext实现从我SecurityContextInjectee中的JwtSecurityContext返回。我想代理(Principal)会将调用转发给它的基础JwtSecurityContext,因此返回我的Principal,但我不确定,最后我更愿意使用我的{{1}而不是将这些值包装在 <xsl:template match="name"> <xsl:copy> <xsl:call-template name="replace"> <!-- Here getting the replaced values --> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:copy> </xsl:template> <xsl:template name="replace"> <xsl:param name="text"/> <xsl:param name="searchString">'</xsl:param> <xsl:param name="replaceString">''</xsl:param> <xsl:choose> <xsl:when test="contains($text,$searchString)"> <xsl:value-of select="substring-before($text,$searchString)"/> <xsl:value-of select="$replaceString"/> <!-- recursive call --> <xsl:call-template name="replace"> <xsl:with-param name="text" select="substring-after($text,$searchString)"/> <xsl:with-param name="searchString" select="$searchString"/> <xsl:with-param name="replaceString" select="$replaceString"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template> 实现中。

1 个答案:

答案 0 :(得分:6)

您可以注入161 3277 4704 52456568 0 1340 380 425 3277 4704 52456578 1 1330 380 422 3118 4719 52456588 1 1340 390 415 3109 4732 52456598 1 1340 400 420 3182 4743 52456608 1 1350 410 427 3309 4789 52456618 1 1360 420 446 ... (如this post中所述),然后从那里获取ContainerRequestContext

SecurityContext