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

无情 阅读:225 2021-03-31 12:47:10 评论:0

今天在实现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); 
	} 
}

产生问题得到解决

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
KIKK导航

KIKK导航

关注我们