为了账号安全,请及时绑定邮箱和手机立即绑定

如何确保 Spring Security 安全资源服务器仅接受来自自己应用程序的 JWT 令牌

如何确保 Spring Security 安全资源服务器仅接受来自自己应用程序的 JWT 令牌

慕的地6264312 2024-01-17 10:25:56
我正在将 Spring Security 与 Spring Boot 2.2.0 结合使用,尝试让 Azure AD B2C 正常工作,使用spring-security-oauth2-resource-server:5.2.0和spring-security-oauth2-jose:5.2.0.使用此配置:@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {    @Override    protected void configure(HttpSecurity http) throws Exception {        http.authorizeRequests()            .antMatchers("/api/**")            .authenticated()            .and()            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);    }}与spring.security.oauth2.resourceserver.jwt.jwk-set-uri设置在我的application.properties.我可以从 Azure AD B2C 获取令牌并使用该令牌访问我自己的 API 终结点。但是,如果我使用另一个目录中的令牌,也可以访问端点。我确实在委托人的声明中看到这来自另一个天蓝色目录。这是我需要在我的应用程序中手动添加的内容(测试应用程序 ID 是否与声明中匹配)?或者我应该添加一些我还没有完成的其他配置?我还尝试使用添加我自己的 JwtDecoder bean JwtDecoders.fromOidcIssuerLocation("https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow");,但这给出了:java.lang.IllegalStateException: The Issuer "https://mycompb2ctestorg.b2clogin.com/60780907-bc3a-469a-82d1-b89ffed655af/v2.0/" provided in the configuration did not match the requested issuer "https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow"另外,使用:spring.security.oauth2.resourceserver.jwt.issuer-uri=https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/?p=B2C_1_ropc_flow给出与尝试声明我自己的JwtDecoderbean 相同的异常。
查看完整描述

3 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

我知道我参加聚会迟到了,但当前答案中缺少一些信息。


非法状态异常:


provided in the configuration did not match the requested issuer 

很可能是由于 @Dragana Le Mitova 已经在 issues-uri 属性末尾的斜线提到的那样引起的。这需要设置为:


spring.security.oauth2.resourceserver.jwt.issuer-uri=https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0

然后 Spring 将自动提取 OAuth 资源服务器的配置https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/.well-known/openid-configuration。


为了确保我们只接受来自 Azure 应用程序的 JWT,我们需要检查 JWT 的受众 (aud) 属性。对于 Azure 应用程序,这通常与客户端/应用程序 ID 相同。正如 @Wim Deblauwe 已经回答的那样,这是通过JwtDecoder. Spring Security 甚至在他们的文档中为我们提供了一个自定义 JWT 验证器的示例,其中他们实现了受众声明检查。这是通过在JwtDecoderbean 中提供我们自己的验证器来完成的。


受众(aud)声明验证器:


public class AudienceValidator implements OAuth2TokenValidator<Jwt> {

    OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);


    public OAuth2TokenValidatorResult validate(Jwt jwt) {

        if (jwt.getAudience().contains("messaging")) {

            return OAuth2TokenValidatorResult.success();

        } else {

            return OAuth2TokenValidatorResult.failure(error);

        }

    }

}

Jwt解码器:


@Bean

JwtDecoder jwtDecoder() {

    NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)

        JwtDecoders.withOidcIssuerLocation(issuerUri);


    OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator();

    OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);

    OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);


    jwtDecoder.setJwtValidator(withAudience);


    return jwtDecoder;

}

这与 @Wim Deblauwe 提供的答案略有不同,我们使用JwtValidators.createDefaultWithIssuer(issuerUri)而不是创建验证器JwtValidators.createDefault()。这很重要,因为我们本质上要检查 3 个 JWT 属性:


到期日

发行人

观众

我们JwtValidators.createDefault()只为过期属性创建一个验证器。我们为JwtValidators.createDefaultWithIssuer(issuerUri)过期和发行者属性创建验证器。JwtValidators.createDefaultWithIssuer(issuerUri)也是 Spring Security 设置 issues-uri 属性时的默认行为。


如果您想更深入地了解,我们目前添加自定义验证器的方式是否是最佳方式正在进行讨论。


查看完整回答
反对 回复 2024-01-17
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

在阅读了Spring Security 文档中的自定义令牌验证器后,我添加了一个自定义验证器来检查受众声明,以确保令牌是为我自己的应用程序颁发的。为此,请创建此验证器类:


private static class AudienceValidator implements OAuth2TokenValidator<Jwt> {


    @Override

    public OAuth2TokenValidatorResult validate(Jwt token) {

        if (token.getAudience().contains("my-application-id-here")) {

            return OAuth2TokenValidatorResult.success();

        } else {

            return OAuth2TokenValidatorResult.failure(

                    new OAuth2Error("invalid_token", "The audience is not as expected, got " + token.getAudience(),

                                    null));

        }

    }

}

并通过JwtDecoder在配置类中声明您自己的 bean来使用它WebSecurityConfigurerAdapter:


@Bean

public JwtDecoder jwtDecoder() {

    NimbusJwtDecoder result = NimbusJwtDecoder.withJwkSetUri(properties.getJwt().getJwkSetUri()).build();

    result.setJwtValidator(

            new DelegatingOAuth2TokenValidator<Jwt>(

                   JwtValidators.createDefault(), 

                   new AudienceValidator()) 

            );

    return result;

}

默认验证器将检查时间戳等内容。如果没问题,AudienceValidator 将检查受众声明。


注意:您在验证器中传递的顺序DelegatingOAuth2TokenValidator定义了 JWT 令牌的检查顺序。在此示例中,在观众之前检查时间戳。如果你想让观众先检查,你需要把它放在构造函数的前面DelegatingOAuth2TokenValidator


查看完整回答
反对 回复 2024-01-17
?
动漫人物

TA贡献1815条经验 获得超10个赞

我怀疑您在尝试声明自己的JwtDecoder光束时遇到的异常来自缺少的斜杠。


请注意,“请求的发行者”始终缺少尾部斜杠,即使在配置中明确指定了尾部斜杠。


按照规范的要求, Spring Security在附加之前会从颁发者 URI 中删除所有尾部斜杠。但是,在获取配置后,返回的配置的颁发者 URI 与问题 URI 的“清理”版本相匹配,而不是最初提供的版本。


由于fromOidcIssuerLocation()不知道最初提供的颁发者 URL,因此它会与 cleanIssuer 进行匹配,从而导致所描述的问题。解决这个问题的最简单方法是在fromOidcIssuerLocation()中进行清理,然后仍然可以使用原始版本进行匹配。


另一条注释与您提出的第一个问题相关。


如果我知道您的 API 标识符 + 您的租户 ID,我可以使用客户端凭据获取您的 API 的访问令牌!令牌不会包含范围或角色,它不能。因此,检查是否存在有效的委派权限(也称为范围)或有效的应用程序权限(在角色声明中)至关重要。


看看这个特定的代码。


 JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();


        TokenValidationParameters validationParameters = new TokenValidationParameters

        {

            // We accept both the App Id URI and the AppId of this service application

            ValidAudiences = new[] { audience, clientId },


            // Supports both the Azure AD V1 and V2 endpoint

            ValidIssuers = new[] { issuer, $"{issuer}/v2.0" },

            IssuerSigningKeys = signingKeys

        };


查看完整回答
反对 回复 2024-01-17
  • 3 回答
  • 0 关注
  • 170 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信