如何移除Spring Security认证流程中的指定调试日志记录?
Alright, let's figure out how to get rid of that debug log line when a user isn't found in AbstractUserDetailsAuthenticationProvider.authenticate(). There are two solid approaches depending on whether you want to tweak code or just adjust logging configurations.
Since AbstractUserDetailsAuthenticationProvider is a concrete class we can extend, we can override the relevant methods to remove the problematic log line entirely. Here's how to do it:
Create a custom provider class that inherits from
AbstractUserDetailsAuthenticationProvider
We'll override theretrieveUsermethod (where the "user not found" log is triggered) and replicate the original logic—minus the debug log line. We'll also keep theadditionalAuthenticationChecksmethod if we don't need to modify password validation logic.import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.util.Assert; public class CustomUserDetailsAuthProvider extends AbstractUserDetailsAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // Keep the original password validation logic unchanged if (authentication.getCredentials() == null) { this.logger.debug("Failed to authenticate since no credentials provided"); throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } String presentedPassword = authentication.getCredentials().toString(); if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { this.logger.debug("Failed to authenticate since password does not match stored value"); throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } } @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { prepareTimingAttackProtection(); try { UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username); if (loadedUser == null) { // Removed the original logger.debug("User '" + username + "' not found"); line here throw new UsernameNotFoundException("User " + username + " not found"); } return loadedUser; } catch (UsernameNotFoundException ex) { mitigateAgainstTimingAttack(authentication); throw ex; } catch (Exception ex) { mitigateAgainstTimingAttack(authentication); throw new InternalAuthenticationServiceException(ex.getMessage(), ex); } } }Register your custom provider in Spring Security's configuration
Replace the default provider with your custom one in yourSecurityFilterChainbean:import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authenticationProvider(new CustomUserDetailsAuthProvider()) // Add your other security configurations here (authorizeHttpRequests, formLogin, etc.) ; return http.build(); }
This approach completely eliminates the log line from being generated at all, which is the cleanest solution if you're comfortable modifying code.
If you don't want to touch code, you can configure your logging framework (like Logback or Log4j2) to filter out that specific debug log message.
For Logback (logback.xml)
Add a filter to the logger for AbstractUserDetailsAuthenticationProvider to block messages containing the "not found" string:
<configuration> <!-- Your existing logging configs --> <logger name="org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider" level="DEBUG"> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator> <!-- Only accept logs that DON'T contain "not found" --> <expression>!message.contains("not found")</expression> </evaluator> <OnMismatch>DENY</OnMismatch> <OnMatch>ACCEPT</OnMatch> </filter> </logger> </configuration>
For Log4j2 (log4j2.xml)
Use a script filter to achieve the same result:
<Configuration> <!-- Your existing logging configs --> <Logger name="org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider" level="debug"> <Filters> <ScriptFilter onMatch="ACCEPT" onMismatch="DENY"> <Script language="javascript">!logEvent.getMessage().includes("not found")</Script> </ScriptFilter> </Filters> </Logger> </Configuration>
Note: This method doesn't stop the log from being generated, but it prevents it from being output to your logs. It's great for quick fixes without code changes.
内容的提问来源于stack exchange,提问作者100MIL

