SpringSecurity系列(21)-Oauth2资源服务器异常处理源码分析及⾃定义异常
信息
transmission
资源服务器异常
表现
⾸先我们看下可能会发⽣的⼏个异常。
未传认证消息头: 传个错误令牌:
源码分析
接下传⼊⼀个错误Token分析下源码,康康这个异常是怎么处理的。
在之前的中,我们分析过,资源服务器是由OAuth2AuthenticationProcessingFilter过滤器来完成的,如果发⽣OAuth2Exception 异常,也⾃⾏进⾏了处理。
iss
1. 抛出异常
我们知道资源服务器,获取到Token以后,会去授权服务器校验令牌,获取信息。调⽤的是RemoteTokenServices的loadAuthentication ⽅法。
可以看到这个令牌,调⽤远程校验的结果失败了,远程校验结果不是active时,就会抛出InvalidTokenException(不可⽤令牌)异常。
gvmt
2. 异常捕获
InvalidTokenException(不可⽤令牌)异常,是在OAuth2AuthenticationProcessingFilter过滤器中抛出的,所以会被它catch到。
3. AuthenticationEntryPoint
在catch中,异常交给了AuthenticationEntryPoint 处理,这⾥默认使⽤的是OAuth2AuthenticationEntryPoint对象。
AuthenticationEntryPoint 的commence调⽤的是其抽象类的doHandle⽅法。也会调⽤翻译器进⾏处理。然后调⽤handleHttpEntityRespon进⾏响应,经过序列化,最终返回错误信息给前端。
catch (OAuth2Exception failed ) {
SecurityContextHolder .clearContext ();
if (debug ) {
英文字母26个字母表
logger .debug ("Authentication request failed: " + failed );
}
// 发布认证失败事件
eventPublisher .publishAuthenticationFailure (new BadCredentialsException (failed .getMessage (), failed ),
new PreAuthenticatedAuthenticationToken ("access-token", "N/A"));
// 调⽤AuthenticationEntryPoint 处理异常
authenticationEntryPoint .commence (request , respon ,
new InsufficientAuthenticationException (failed .getMessage (), failed ));
return ;
}
⾃定义异常
我们知道最终是通过AuthenticationEntryPoint 处理异常的,那么⾃定义处理类实现AuthenticationEntryPoint 接⼝就⾏了。
1. ⾃定义AuthenticationEntryPoint
伤害英文protected final void doHandle (HttpServletRequest request , HttpServletRespon respon , Exception authException )
throws IOException , ServletException {
try {
// 调⽤异常翻译器
ResponEntity <?> result = exceptionTranslator .translate (authException );
result = enhanceRespon (result , authException );
// 处理ResponEntity
exceptionRenderer .handleHttpEntityRespon (result , new ServletWebRequest (request , respon ));
respon .flushBuffer ();
}
catch (ServletException e ) {
中学辅导if (handlerExceptionResolver .resolveException (request , respon , this , e ) == null ) {
throw e ;
}
}
catch (IOException e ) {
throw e ;
}
catch (RuntimeException e ) {
throw e ;
}
catch (Exception e ) {
// Wrap other Exceptions. The are not expected to happen
throw new RuntimeException (e );
}
英汉互译词典
}
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
private ObjectMapper objectMapper = new ObjectMapper ();
@Override
public void commence (HttpServletRequest request , HttpServletRespon respon ,
AuthenticationException authException ) throws ServletException {
甜点英文
try {
// 1. 检查看服务端是否已将数据输出到客户端,如果已返回,则不处理
if (respon .isCommitted ()) {
return ;
}
// 2. 封装结果信息,应该使⽤统⼀结果集封装,这⾥使⽤Map
respon .tStatus (HttpStatus .UNAUTHORIZED .value ());
respon .tCharacterEncoding ("UTF-8");
respon .tContentType ("application/json;chart=utf-8");
Map <String , Object > result = new HashMap <>();
result .put ("code", 401);
result .put ("msg", authException .getMessage ());
result .put ("result", "认证失败");
objectMapper .writeValue (respon .getOutputStream (), result );
} catch (Exception e ) {
throw new ServletException (e );
}
}
}
2. ResourceServer 添加配置
3.
测试
@Configuration @EnableResourceServer //标识为资源服务
@EnableWebSecurity(debug = true )
@EnableGlobalMethodSecurity(prePostEnabled = true , curedEnabled = true , jsr250Enabled = true )public class MyResourceServerConfig extends ResourceServerConfigurerAdapter {
public MyResourceServerConfig () {
super ();
}
乐宁@Autowired
MyAuthenticationEntryPoint myAuthenticationEntryPoint ;
@Override
public void configure (ResourceServerSecurityConfigurer resources ) throws Exception { resources .authenticationEntryPoint (myAuthenticationEntryPoint );
}
@Override
moderate是什么意思
public void configure (HttpSecurity http ) throws Exception {
super .configure (http );
}
// 密码解析器
@Bean
public BCryptPasswordEncoder passwordEncoder () {
return new BCryptPasswordEncoder ();
}
}