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

产生问题得到解决

### 回答1: 这个错误提示是因为Spring Security没有找到对应的AuthenticationProvider来处理UsernamePasswordAuthenticationToken类型的认证请求。可能是因为你没有配置相应的AuthenticationProvider或者配置有误。你需要检查你的Spring Security配置文件,确保正确配置了AuthenticationProvider,并且该Provider支持处理UsernamePasswordAuthenticationToken类型的认证请求。 ### 回答2: org.springframework.security.authentication.usernamepasswordauthenticationtoken 是 Spring Security 中的一种身份验证令牌,用于基于用户名和密码的身份验证。该异常表示未找到适当的身份验证提供程序,即在 Spring Security 中没有注册与该令牌对应的身份验证提供程序。 要解决这个问题,需要在 Spring Security 的配置文件中添加一个身份验证提供程序来处理该令牌。可以使用 DaoAuthenticationProvider 来基于数据库提供身份验证,或使用 InMemoryAuthenticationProvider 来在内存中存储用户详细信息。以下是一个简单的 Spring Security 配置示例,演示如何为 org.springframework.security.authentication.usernamepasswordauthenticationtoken 添加身份验证提供程序: ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService); authProvider.setPasswordEncoder(passwordEncoder()); auth.authenticationProvider(authProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/") .permitAll() .and() .logout() .permitAll(); } } ``` 在上面的配置中,我们创建了一个 DaoAuthenticationProvider,并设置其 UserDetailsService 和 PasswordEncoder。然后,我们使用 auth.authenticationProvider() 方法将其添加到身份验证管理器中。 最后,我们还配置了基本的 HTTP 安全性设置,以确保所有请求都需要身份验证,可以通过自定义登录页面进行身份验证,以及注销登录。 通过这些配置,我们就可以在 Spring Security 中处理 org.springframework.security.authentication.usernamepasswordauthenticationtoken 令牌,并进行相应的身份验证操作。 ### 回答3: 在使用 Spring Security 进行身份验证的过程中,可能会遇到 "No AuthenticationProvider found" 的异常,即无法找到对应的身份验证提供者(AuthenticationProvider)。这个问题通常是由于配置错误或缺失导致的。 首先,在 Spring Security 配置文件中需要明确指定身份验证提供者,例如: ``` <authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider> </authentication-manager> ``` 上面的代码中,使用了基于 JDBC 的用户服务作为身份验证提供者,并通过 data-source-ref 属性指定了数据源。这样就可以在使用用户名和密码进行身份验证时,从数据源中查询用户信息并进行身份验证。 除了 JDBC 用户服务,还有其他身份验证提供者可供选择,例如 InMemoryUserDetailsManager、LdapAuthenticationProvider 等等。需要根据实际需求选择并配置相应的提供者。 另外,还需要确认用户名和密码的传递方式是否正确。通常包括用户填写表单、提交表单并传递用户名和密码参数等步骤。如果用户登录请求没有正常传递用户名和密码参数,就会导致身份验证提供者找不到有效的用户信息而抛出上述异常。 总之,在出现 "No AuthenticationProvider found" 的异常时,需要检查 Spring Security 配置文件、身份验证提供者和用户名密码传递方式,并根据实际情况进行调整和修改。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值