Spring Security 添加一个自定义Exception Mapping

Authentication Events

Spring Security对于成功或失败的每个身份验证,分别会触发AuthenticationSuccessEvent或AbstractAuthenticationFailureEvent。要侦听这些事件,你必须首先发布一个AuthenticationEventPublisher。Spring Security提供了一个默认的AuthenticationEventPublisher实现,DefaultAuthenticationEventPublisher。

今天讲一下如何添加一个自定义的Exception Mapping。

Adding Exception Mappings

在讲之前我们看一下DefaultAuthenticationEventPublisher中已经提供了哪些Exception Mappings。

ExceptionEvent
BadCredentialsExceptionAuthenticationFailureBadCredentialsEvent
UsernameNotFoundExceptionAuthenticationFailureBadCredentialsEvent
BadCredentialsExceptionAuthenticationFailureBadCredentialsEvent
AccountExpiredExceptionAuthenticationFailureExpiredEvent
ProviderNotFoundExceptionAuthenticationFailureProviderNotFoundEvent
DisabledExceptionAuthenticationFailureDisabledEvent
LockedExceptionAuthenticationFailureLockedEvent
AuthenticationServiceExceptionAuthenticationFailureServiceExceptionEvent
CredentialsExpiredExceptionAuthenticationFailureCredentialsExpiredEvent
InvalidBearerTokenExceptionAuthenticationFailureBadCredentialsEvent

也就是说在默认的情况下Spring Security在身份验证异常时将会触发上述对应的事件。我们针对上面的事件可以进行继承实现自己的一些逻辑。

但如果我们要添加一个自定义的Exception Mapping我们可以这样做:
假设我们定义一个密码为空的异常,并且我认为它属于AuthenticationFailureBadCredentialsEvent的一种。

定义CustomNullPasswordException类,我这里继承的是UsernameNotFoundException ,UsernameNotFoundException实际上继承的是AuthenticationException,这里因为自己的逻辑关系,我想在UserDetailsService的实现类里针对密码为空时抛出自己自定义的异常,主要逻辑就是在UserDetailsService 的loadUserByUsername(String username) 接口里根据username查询用户信息然后判断密码是否为空。你不必按我的逻辑来你可以直接继承AuthenticationException 根据自己的实际情况来定义异常。

public class CustomNullPasswordException extends UsernameNotFoundException {

	private static final long serialVersionUID = 1L;
	private Map<String, Object> map;

	public CustomNullPasswordException(String msg) {
		super(msg);
	}

	public CustomNullPasswordException(Map<String, Object> map, String msg) {
		super(msg);
		this.map = map;
	}

	public Map<String, Object> getMap() {
		return map;
	}

	public void setMap(Map<String, Object> map) {
		this.map = map;
	}
}

UserDetailsServiceImpl 这里我就一笔代理,知道这个异常是在哪抛出的就行了。

public class UserDetailsServiceImpl implements UserDetailsService {
	@Override
	public UserDetails loadUserByUsername(String agentCode) throws UsernameNotFoundException {
		......
		
		if(null == userDetails.getPassword() || "" == userDetails.getPassword()){
			throw new CustomNullPasswordException(map, "密码为空,请设置密码!");
		}
		......
	}
}

然后我们添加Exception 和 Event 的映射关系,我这里是通过Properties 对象的put方法把 CustomNullPasswordException 全限定类名,和AuthenticationFailureBadCredentialsEvent全限定类名 作为key和value 添加到Properties中然后在通过DefaultAuthenticationEventPublisher 的setAdditionalExceptionMappings方法进行映射的,下面是大体的代码实例。如果抛出CustomNullPasswordException异常就会对应到AuthenticationFailureBadCredentialsEvent事件上来。

@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	......
	
	@Autowired
	private ApplicationEventPublisher applicationEventPublisher;
	
	/**
	 * 默认DefaultAuthenticationEventPublisher添加事件
	 * 
	 * @return
	 */
	public AuthenticationEventPublisher authenticationEventPublisher() {
		DefaultAuthenticationEventPublisher event = new DefaultAuthenticationEventPublisher(applicationEventPublisher);
		Properties additionalExceptionMappings = new Properties();
		// 处理密码为空的情况
		additionalExceptionMappings.put("com.xxxxx.CustomNullPasswordException",
				"org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent");
		// 设置自定义异常事件
		event.setAdditionalExceptionMappings(additionalExceptionMappings);
		return event;
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationEventPublisher(authenticationEventPublisher());
	}

	......
}

当然官方也给了Adding Exception Mappings的介绍,大家也可以参考官方的方式来配置。
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#adding-exception-mappings
配置例子如下:

@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    Map<Class<? extends AuthenticationException>,
        Class<? extends AbstractAuthenticationFailureEvent>> mapping =
            Collections.singletonMap(FooException.class, FooEvent.class);
    AuthenticationEventPublisher authenticationEventPublisher =
        new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    authenticationEventPublisher.setAdditionalExceptionMappings(mapping);
    return authenticationEventPublisher;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值