自定义认证提供者中Autowiring注入为Null问题求助
Hey Francesco, sorry to hear you're stuck with this null pointer issue in your custom Authentication Provider. Let's break down the most common causes and fixes for this problem:
1. Make Sure Your Custom Authentication Provider is Spring-Managed
If you're manually instantiating your CustomAuthenticationProvider (e.g., using new CustomAuthenticationProvider() in your SecurityConfig), Spring won't handle dependency injection for it. Instead, mark the provider class with a Spring stereotype annotation like @Component or @Service so Spring creates and manages its instance:
@Component public class CustomAuthenticationProvider implements AuthenticationProvider { // Field injection (or constructor injection, preferred) @Autowired private CustomUserDetailsService customUserDetailsService; // Your authenticate() and supports() implementations here }
2. Inject the Provider in SecurityConfig (Don't New It)
In your SecurityConfig, avoid manually creating the provider instance. Instead, let Spring inject it into the configuration class, then pass it to AuthenticationManagerBuilder:
@Configuration @EnableWebSecurity public class SecurityConfig { // Inject the Spring-managed provider private final CustomAuthenticationProvider customAuthProvider; // Constructor injection (recommended over field injection) public SecurityConfig(CustomAuthenticationProvider customAuthProvider) { this.customAuthProvider = customAuthProvider; } @Autowired public void configureAuth(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthProvider); } // Rest of your security configuration... }
3. Verify Your CustomUserDetailsService is Spring-Managed Too
Double-check that your CustomUserDetailsService has a @Service or @Component annotation—Spring can't inject a bean it doesn't know about:
@Service public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // Your implementation here } }
4. Confirm Component Scan Coverage
Ensure all your security-related classes (including SecurityConfig, the provider, and user details service) are within Spring's component scan scope. If your main application class is in a parent package (e.g., esercizio), sub-packages like esercizio.security are scanned by default. If not, explicitly define the scan packages in your @SpringBootApplication annotation:
@SpringBootApplication(scanBasePackages = {"esercizio.security", "esercizio.service"}) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
5. Switch to Constructor Injection (More Reliable)
Field injection with @Autowired can sometimes lead to timing issues in security beans. Constructor injection guarantees dependencies are resolved when the bean is created, eliminating null pointers:
@Component public class CustomAuthenticationProvider implements AuthenticationProvider { private final CustomUserDetailsService userDetailsService; // No @Autowired needed in Spring 4.3+ for single-constructor beans public CustomAuthenticationProvider(CustomUserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // userDetailsService will never be null here String username = authentication.getName(); UserDetails user = userDetailsService.loadUserByUsername(username); // Rest of your authentication logic } @Override public boolean supports(Class<?> authentication) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } }
Debugging Tip
If you're still stuck, enable Spring's debug logging for bean creation to see if your beans are being registered and injected correctly. Add this to your application.properties:
logging.level.org.springframework.beans.factory=DEBUG
You'll see detailed logs about which beans are created, their dependencies, and any injection failures.
内容的提问来源于stack exchange,提问作者Francesco Secondo Finucci

