【发布时间】:2018-08-08 13:26:34
【问题描述】:
我正在遵循指南here,该指南具有以下 sn-p 代码,用于从 Spring Boot Actuator 审计 Spring Security 登录尝试
@Component
public class LoginAttemptsLogger {
@EventListener
public void auditEventHappened(
AuditApplicationEvent auditApplicationEvent) {
AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();
System.out.println("Principal " + auditEvent.getPrincipal()
+ " - " + auditEvent.getType());
WebAuthenticationDetails details =
(WebAuthenticationDetails) auditEvent.getData().get("details");
System.out.println("Remote IP address: "
+ details.getRemoteAddress());
System.out.println(" Session Id: " + details.getSessionId());
}
}
但是当我使用这段代码时,我得到了错误
java.util.LinkedHashMap cannot be cast to org.springframework.security.web.authentication.WebAuthenticationDetails
我正在使用 Spring Boot 1.5.10.RELEASE 和 Spring Boot Actuator 使用无状态 OAuth2 JWT 安全配置。如果我删除有关details 的部分,那么它工作正常。
edit:所以我刚刚发现我的详细信息返回的值与WebAuthenticationDetails 的属性不同。我的详细信息包含grant_type、范围和用户名,而不是转换为WebAuthenticationDetails 所需的remoteAddress 和sessionId。有趣的是,当我访问执行器端点/auditevents 时,详细信息字段的值包含 remoteAddress 和 sessionId。嗯。所以这绝对意味着这是因为我使用的是 OAuth2 但我不知道究竟是什么原因。
edit2:我还注意到它只发布密码/client_credentials 授权类型的事件。如果可能的话,我也想为 refresh_token 授权类型使用相同的侦听器
edit3:这是我的授权服务器配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DataSource dataSource;
@Value("${tokenSigningKey}")
private String tokenSigningKey;
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
CustomJwtAccessTokenConverter accessTokenConverter = new CustomJwtAccessTokenConverter();
accessTokenConverter.setSigningKey(tokenSigningKey);
return accessTokenConverter;
}
@Bean
public TokenStore tokenStore() {
return new CustomJwtJdbcTokenStore(accessTokenConverter(), dataSource);
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomAccessTokenEnhancer();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new CustomPasswordEncoder();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource).passwordEncoder(passwordEncoder());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.passwordEncoder(passwordEncoder());
security.checkTokenAccess("isAuthenticated()");
}
}
【问题讨论】:
-
教程不是1.5.2的吗?
-
@LanceToth 确实如此。也许这就是问题所在,但我认为这样的重大变化不会出现在增量版本中。我会尝试切换到 1.5.2 看看是否能解决它
-
所以,@LanceToth,本教程使用 1.5.10 和用户名/密码验证对我有用。问题可能出在无状态 OAuth2 JWT 上吗?可能那个
AuthenticationProvider发布的Authentication不一样。 -
@zero01alpha,我看到的行为是它正在发布一个
OAuth2AuthenticationDetails(它确实有 sessionId 和 remoteAddress),所以我认为我的设置与你的有点不同。您是否认为发布更多 OAuth2 配置会有所帮助,例如你在用@EnableOAuth2Sso吗? -
谢谢@zero01alpha,这对我很有帮助,因为在我看到你的配置之前我误解了你的用例。我已经在下面发布了我的答案。希望对您有所帮助。
标签: java spring spring-boot spring-security spring-boot-actuator