解码 jwt 时,AuthenticationEvent 不会因错误而发布
AuthenticationEvent is not published on error while decoding jwt
由于我的验证器失败,在尝试解码 Jwt 时发生错误,我无法捕获身份验证失败事件。我正在使用 Spring 安全 5.2.1。请注意,当我根本不在 'Authorization' header 中传递令牌时,我会捕获授权失败事件。我想必须使用 spring 配置来完成一些额外的配置。
抛出的异常:
org.springframework.security.oauth2.core.OAuth2AuthenticationException: An
error occurred while attempting to decode the Jwt: This aud claim does not
contain configured audience
审核按照此处所述实施:https://www.baeldung.com/spring-boot-authentication-audit
当前 spring 安全配置:
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final OAuth2Error INVALID_AUDIENCE =
new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST,
"This aud claim does not contain configured audience",
"https://tools.ietf.org/html/rfc6750#section-3.1");
@Value("${spring.security.oauth2.claim-to-validate.audience}")
private String audience;
@Value("${spring.security.oauth2.claim-to-validate.scope}")
private String scope;
@Value("${spring.security.oauth2.resourceserver.jwt.public-key-location:#{null}}")
private RSAPublicKey publicKeyLocation;
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:#{null}}")
private String jwkSetUri;
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri:#{null}}")
private String issuerUri;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/v1/resource/**")
.hasAuthority("SCOPE_" + scope)
.and()
.oauth2ResourceServer()
.jwt();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
@Bean
public JwtDecoder jwtDecoder() {
final OAuth2TokenValidator<Jwt> withAudience = audienceValidator(audience);
final JwtDecoder jwtDecoder;
if (publicKeyLocation != null) {
jwtDecoder = NimbusJwtDecoder.withPublicKey(publicKeyLocation).build();
} else if (StringUtils.hasLength(jwkSetUri)) {
jwtDecoder = NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
} else if (StringUtils.hasLength(issuerUri)) {
jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuerUri);
} else {
throw new IllegalStateException(
"Invalid OAuth2 configuration: provide value for any of " +
"'publicKeyLocation', 'jwkSetUri' or 'issuerUri'");
}
((NimbusJwtDecoder) jwtDecoder).setJwtValidator(withAudience);
return jwtDecoder;
}
OAuth2TokenValidator<Jwt> audienceValidator(String audience) {
return jwt -> {
Assert.notNull(jwt, "token cannot be null");
final List<String> audiences = jwt.getAudience();
return audiences.contains(audience) ?
OAuth2TokenValidatorResult.success() :
OAuth2TokenValidatorResult.failure(INVALID_AUDIENCE);
};
}
}
将 Spring 安全更新到 5.3.0 或更高版本并在 Spring 安全配置自定义 AuthenticationEventPublisher bean 中声明,如下所示:
@Autowired
private ApplicationEventPublisher publisher;
@Bean
public AuthenticationEventPublisher authenticationEventPublisher() {
final Properties properties = new Properties();
properties.put(
OAuth2AuthenticationException.class.getCanonicalName(),
AuthenticationFailureBadCredentialsEvent.class.getCanonicalName());
final DefaultAuthenticationEventPublisher eventPublisher = new DefaultAuthenticationEventPublisher(publisher);
eventPublisher.setAdditionalExceptionMappings(properties);
return eventPublisher;
}
请注意,在 5.3.0 中,您可以直接添加没有 Properties 结构的映射。
如果您需要继续使用 5.2.x,请使用此处指出的解决方法:https://github.com/spring-projects/spring-security/issues/7793
由于我的验证器失败,在尝试解码 Jwt 时发生错误,我无法捕获身份验证失败事件。我正在使用 Spring 安全 5.2.1。请注意,当我根本不在 'Authorization' header 中传递令牌时,我会捕获授权失败事件。我想必须使用 spring 配置来完成一些额外的配置。
抛出的异常:
org.springframework.security.oauth2.core.OAuth2AuthenticationException: An
error occurred while attempting to decode the Jwt: This aud claim does not
contain configured audience
审核按照此处所述实施:https://www.baeldung.com/spring-boot-authentication-audit
当前 spring 安全配置:
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final OAuth2Error INVALID_AUDIENCE =
new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST,
"This aud claim does not contain configured audience",
"https://tools.ietf.org/html/rfc6750#section-3.1");
@Value("${spring.security.oauth2.claim-to-validate.audience}")
private String audience;
@Value("${spring.security.oauth2.claim-to-validate.scope}")
private String scope;
@Value("${spring.security.oauth2.resourceserver.jwt.public-key-location:#{null}}")
private RSAPublicKey publicKeyLocation;
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:#{null}}")
private String jwkSetUri;
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri:#{null}}")
private String issuerUri;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/v1/resource/**")
.hasAuthority("SCOPE_" + scope)
.and()
.oauth2ResourceServer()
.jwt();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
@Bean
public JwtDecoder jwtDecoder() {
final OAuth2TokenValidator<Jwt> withAudience = audienceValidator(audience);
final JwtDecoder jwtDecoder;
if (publicKeyLocation != null) {
jwtDecoder = NimbusJwtDecoder.withPublicKey(publicKeyLocation).build();
} else if (StringUtils.hasLength(jwkSetUri)) {
jwtDecoder = NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
} else if (StringUtils.hasLength(issuerUri)) {
jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuerUri);
} else {
throw new IllegalStateException(
"Invalid OAuth2 configuration: provide value for any of " +
"'publicKeyLocation', 'jwkSetUri' or 'issuerUri'");
}
((NimbusJwtDecoder) jwtDecoder).setJwtValidator(withAudience);
return jwtDecoder;
}
OAuth2TokenValidator<Jwt> audienceValidator(String audience) {
return jwt -> {
Assert.notNull(jwt, "token cannot be null");
final List<String> audiences = jwt.getAudience();
return audiences.contains(audience) ?
OAuth2TokenValidatorResult.success() :
OAuth2TokenValidatorResult.failure(INVALID_AUDIENCE);
};
}
}
将 Spring 安全更新到 5.3.0 或更高版本并在 Spring 安全配置自定义 AuthenticationEventPublisher bean 中声明,如下所示:
@Autowired
private ApplicationEventPublisher publisher;
@Bean
public AuthenticationEventPublisher authenticationEventPublisher() {
final Properties properties = new Properties();
properties.put(
OAuth2AuthenticationException.class.getCanonicalName(),
AuthenticationFailureBadCredentialsEvent.class.getCanonicalName());
final DefaultAuthenticationEventPublisher eventPublisher = new DefaultAuthenticationEventPublisher(publisher);
eventPublisher.setAdditionalExceptionMappings(properties);
return eventPublisher;
}
请注意,在 5.3.0 中,您可以直接添加没有 Properties 结构的映射。
如果您需要继续使用 5.2.x,请使用此处指出的解决方法:https://github.com/spring-projects/spring-security/issues/7793