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

Posted 在奋斗的大道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringSecurity 提示ProviderNotFoundException: No AuthenticationProvider found for ****相关的知识,希望对你有一定的参考价值。

今天在实现SpringSecurity 集成多种认证方式:密码模式+ 验证码模式 时,密码模式正常返回执行并返回Token ,验证码模式:总是提示上述错误信息:ProviderNotFoundException: No AuthenticationProvider found for ****

问题解决:

 

报错代码发生在:ProviderManager.authenticate()方法的235行,错误源码输出如下:

源码上已经标识产生错误的原因: provider.authenticate(authentication) 代码中provider 为null 或者parent.authenticate(authentication) 代码中 parent 为空触发错误信息。

ProviderManager.java 类实例化详解分析:

第一步:WebSecurityConfigurerAdapter适配器类中有一个config方法

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

第二步:可以通过AuthenticationManagerBuilder对象的authenticationProvider方法添加AuthenticationProvider认证对象,看下authenticationProvider方法:

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

第三步:上面的是将AuthenticationProvider对象加入认证链中,下面的代码就是创建ProviderManager对象并初始化认证连:

@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;
	

通过上述三步,完成ProviderManager 实例化过程。

 

错误代码:

WebSecurityConfig 配置:

@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;
    

   

在上述配置文件中,定义了两个Provider 但是在代码跟踪中仅仅发现DaoAuthenticationProvider 实例化成功,另外一个失败

正确代码:

WebSecurityConfig 配置:

@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);
	

产生问题得到解决

以上是关于SpringSecurity 提示ProviderNotFoundException: No AuthenticationProvider found for ****的主要内容,如果未能解决你的问题,请参考以下文章

SpringSecurity登录原理(源码级讲解)

springSecurity手动登录

springsecurity简单用过后的一些笔记

okta oauth2 Spring security 所有受保护的页面重定向到登录

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

(转)解决dubbox-demo-provider.xml报错的问题:提示Failed to read schema document