SpringSecurity 提示ProviderNotFoundException: No AuthenticationProvider found for ****

Today, when implementing Spring Security to integrate multiple authentication methods: password mode + verification code mode, the password mode returns to execution normally and returns Token, verification code mode: always prompts the above error message: ProviderNotFoundException: No AuthenticationProvider found for ****

problem solved:

 

The error code occurs at line 235 of the ProviderManager.authenticate() method, and the error source code output is as follows:

The source code has identified the cause of the error: provider.authenticate(authentication) code in provider is null or parent.authenticate(authentication) code in parent is null to trigger an error message.

Detailed analysis of instantiation of ProviderManager.java class:

The first step: There is a config method in the WebSecurityConfigurerAdapter adapter class

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 加入自定义的安全认证
        auth.userDetailsService(this.authUserDetailsService)
                .passwordEncoder(this.passwordEncoder())
             .and()
                .authenticationProvider(smsAuthenticationProvider())
                .authenticationProvider(authenticationProvider());
    }

Step 2: You can add the AuthenticationProvider authentication object through the authenticationProvider method of the AuthenticationManagerBuilder object, look at the authenticationProvider method:

    private List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
	public AuthenticationManagerBuilder authenticationProvider(
			AuthenticationProvider authenticationProvider) {
		this.authenticationProviders.add(authenticationProvider);
		return this;
	}

Step 3: The above is to add the AuthenticationProvider object to the authentication chain, the following code is to create the ProviderManager object and initialize the authentication connection:

@Override
	protected ProviderManager performBuild() throws Exception {
		if (!isConfigured()) {
			logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
			return null;
		}
		ProviderManager providerManager = new ProviderManager(authenticationProviders,
				parentAuthenticationManager);
		if (eraseCredentials != null) {
			providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
		}
		if (eventPublisher != null) {
			providerManager.setAuthenticationEventPublisher(eventPublisher);
		}
		providerManager = postProcess(providerManager);
		return providerManager;
	}

Through the above three steps, complete the ProviderManager instantiation process.

 

error code:

WebSecurityConfig configuration:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	@Qualifier("userDetailServiceImpl")
	private UserDetailsService userDetailService;

   /**
	 * 自定义Provider
	 */
	@Autowired
	private VerificationCodeProvider verificationCodeProvider;
	
	 /**
     * 认证
     *
     * @return
     */
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        //对默认的UserDetailsService进行覆盖
        authenticationProvider.setUserDetailsService(userDetailService);
        authenticationProvider.setPasswordEncoder(new PasswordEncoder() {
 
            // 对密码未加密
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }
 
            // 判断密码是否正确, rawPassword 用户输入的密码,  encodedPassword 数据库DB的密码,当 userDetailService的loadUserByUsername方法执行完后执行
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
            	return rawPassword.toString().equalsIgnoreCase(encodedPassword);
            }
        });
        return authenticationProvider;
    }

   
}

In the above configuration file, two Providers are defined, but only the DaoAuthenticationProvider instantiation is found successfully in the code trace, and the other one fails.

Correct code:

WebSecurityConfig configuration:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	@Qualifier("userDetailServiceImpl")
	private UserDetailsService userDetailService;
	
	
	
	/**
	 * 自定义Provider
	 */
	@Autowired
	private VerificationCodeProvider verificationCodeProvider;
	

	
	 /**
     * 认证
     *
     * @return
     */
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        //对默认的UserDetailsService进行覆盖
        authenticationProvider.setUserDetailsService(userDetailService);
        authenticationProvider.setPasswordEncoder(new PasswordEncoder() {

            // 对密码未加密
            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }

            // 判断密码是否正确, rawPassword 用户输入的密码,  encodedPassword 数据库DB的密码,当 userDetailService的loadUserByUsername方法执行完后执行
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
            	return rawPassword.toString().equalsIgnoreCase(encodedPassword);
            }
        });
        return authenticationProvider;
    }
    

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		// TODO Auto-generated method stub
		auth.authenticationProvider(authenticationProvider());
		auth.authenticationProvider(verificationCodeProvider);
	}
}

Problem solved

Guess you like

Origin blog.csdn.net/zhouzhiwengang/article/details/112589477