spring security oauth2中UsernameNotFoundException无法在认证失败后被捕获的问题

1.问题描述:

在认证失败后UsernameNotFoundException异常会被默认转换成BadCredentialsException异常,导致不能捕获到UsernameNotFoundException, 一般来说UsernameNotFoundException是用户名错误导致的登录失败,BadCredentialsException是用户名或者密码错误导致的登录失败。如果我们能捕获到UsernameNotFoundException就能很好的区分登录失败是哪种具体的原因,以便在某些时候做一些对应的逻辑处理。

2.解决方案:

在AbstractUserDetailsAuthenticationProvider中有这么一段代码:

public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		//...
			
		if (user == null) {
			cacheWasUsed = false;

			try {
				user = retrieveUser(username,
						(UsernamePasswordAuthenticationToken) authentication);
			}
			catch (UsernameNotFoundException notFound) {
				logger.debug("User '" + username + "' not found");

				if (hideUserNotFoundExceptions) {
					throw new BadCredentialsException(messages.getMessage(
							"AbstractUserDetailsAuthenticationProvider.badCredentials",
							"Bad credentials"));
				} else {
					throw notFound;
				}
			}

			Assert.notNull(user,
					"retrieveUser returned null - a violation of the interface contract");
		}

		// ...
	}

可以看到hideUserNotFoundExceptions为true的时候UsernameNotFoundException就会被转换成BadCredentialsException异常,而hideUserNotFoundExceptions的默认值是true,所以我们只需要修改hideUserNotFoundExceptions为false即可解决问题。以下是具体方案:

在WebSecurityConfigurerAdapter的实现类配置中添加如下配置:

@Primary
@Order(90)
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
	@Autowired
	private UserDetailsService userDetailsService;
	//...
	
	@Override
	public void configure(AuthenticationManagerBuilder auth) {
		auth.authenticationProvider(authenticationProvider());
	}
	
	//可以配置成一个Bean
	private DaoAuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
		//设置hideUserNotFoundExceptions为false
		provider.setHideUserNotFoundExceptions(false);
		//userDetailsService是你自己的userDetailsService实现类,
		//UsernameNotFoundException就是其中抛出来的
		provider.setUserDetailsService(userDetailsService);
		provider.setPasswordEncoder(passwordEncoder());
		return provider;
	}
	
    //...
}

认证失败事件处理:

import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

@Component
public class AuthenticationFailureEvenHandler implements ApplicationListener<AbstractAuthenticationFailureEvent> {
	@Override
	public void onApplicationEvent(AbstractAuthenticationFailureEvent event) {
		AuthenticationException authenticationException = event.getException();
		Authentication authentication = (Authentication) event.getSource();
		handle(authenticationException, authentication);
	}

	public void handle(AuthenticationException exc, Authentication auth){
		//获取一些参数
		String username = (String)auth.getPrincipal();
		Map<String,Object> params= (Map<String,Object>)auth.getDetails();
		
		if (exc instanceof BadCredentialsException){
			//密码错误导致的登录失败
			//TODO...
		}else if(exc instanceof UsernameNotFoundException){
			//用户名不存在导致的登录失败
			//TODO...
		}
	}
}
### 回答1: badcredentialsexception是一个身份验证异常,通常表示提供的凭据无效或不正确。这可能是由于密码错误、用户名错误或其他身份验证问题引起的。在应用程序,可以通过捕获此异常并提供更具体的错误消息来帮助用户解决身份验证问题。 ### 回答2: BadCredentialsExceptionSpring Security 框架抛出的一个异常,表示用户提供的凭据无效。这个异常在登录过程经常被抛出,通常是因为用户的用户名或密码不正确而引起的。 BadCredentialsException 异常是一种运行时异常,属于认证异常的一种,它继承于 AuthenticationException。它通常是在验证用户凭据的过程抛出的。当用户提供的用户名或密码不正确时,就会抛出 BadCredentialsException 异常。 在 Spring Security ,验证用户凭据是通过 AuthenticationManager 来完成的。当有一个 AuthenticationManager 实例时,我们可以通过它的 authenticate 方法来进行认证,该方法会返回一个 Authentication 对象。如果认证通过,该对象会包含用户信息和角色列表等信息,否则就会抛出 BadCredentialsException 异常。 当我们在使用 Spring Security 进行用户认证的过程遇到 BadCredentialsException 异常时,我们需要检查用户提供的凭据是否正确。通常可以检查一下密码是否正确或者用户名是否拼写错误等。另外,我们还可以通过自定义 AuthenticationProvider 来实现自己的身份验证逻辑,以符合特定需求。 总之,BadCredentialsException 异常是由 Spring Security 框架抛出的,它表示用户提供的凭据无效,通常是因为用户名或密码不正确。在使用 Spring Security 进行用户认证的过程,我们需要检查用户提供的凭据是否正确,并可以通过自定义 AuthenticationProvider 来实现自己的身份验证逻辑。 ### 回答3: BadCredentialsExceptionSpring Security的一个异常类,用于表示用户登录时提供的用户身份认证信息(用户名、密码等)无效的情况。 当用户提供的用户名或者密码不正确时,认证过程会抛出BadCredentialsException异常,这也是Spring Security常见的异常之一。如果我们自己实现了用户身份认证过程,可以通过捕获该异常并进行相应的处理来优化用户体验。 通常,处理BadCredentialsException异常的方式有以下几种: 1. 提示用户输入正确的用户名和密码 如果用户提供的用户名或者密码错误,我们可以返回相应的提示信息,让用户重新输入正确的用户名和密码。 2. 记录失败的登录尝试 如果用户连续多次输入错误的用户名或者密码,可能意味着有人试图非法入侵系统。我们可以记录相应的登录尝试信息,并根据相应的策略来限制该用户的登录次数或者封禁该用户的账号。 3. 引导用户完成忘记密码流程 如果用户忘记了自己的密码,我们可以提供相应的找回密码功能,引导用户完成相应的流程,如通过手机号码或者邮箱找回密码。 总之,处理BadCredentialsException需要我们根据具体的业务场景和需求,采取相应的策略和措施,保证我们的应用系统在用户信息方面的安全性和可靠性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值