SpringCloud Alibaba 实战二十七 - Oauth2 认证服务器自定义异常
为了解决上面这些异常,我们首先需要编写不同异常的错误代码:ReturnCode.java
CLIENT_AUTHENTICATION_FAILED(1001,"客户端认证失败"),
USERNAME_OR_PASSWORD_ERROR(1002,"用户名或密码错误"),
UNSUPPORTED_GRANT_TYPE(1003,?"不支持的认证模式");
OAuth2Exception 异常
如上所说我们编写一个自定义异常翻译类 CustomWebResponseExceptionTranslator
@Slf4j
public?class?CustomWebResponseExceptionTranslator?implements?WebResponseExceptionTranslator?{
@Override
public?ResponseEntity<ResultData<String>>?translate(Exception?e)?throws?Exception?{
log.error("认证服务器异常",e);
ResultData<String>?response?=?resolveException(e);
return?new?ResponseEntity<>(response,?HttpStatus.valueOf(response.getHttpStatus()));
}
/**
*?构建返回异常
*?@param?e?exception
*?@return
*/
private?ResultData<String>?resolveException(Exception?e)?{
//?初始值?500
ReturnCode?returnCode?=?ReturnCode.RC500;
int?httpStatus?=?HttpStatus.UNAUTHORIZED.value();
//不支持的认证方式
if(e?instanceof?UnsupportedGrantTypeException){
returnCode?=?ReturnCode.UNSUPPORTED_GRANT_TYPE;
//用户名或密码异常
}else?if(e?instanceof?InvalidGrantException){
returnCode?=?ReturnCode.USERNAME_OR_PASSWORD_ERROR;
}
ResultData<String>?failResponse?=?ResultData.fail(returnCode.getCode(),?returnCode.getMessage());
failResponse.setHttpStatus(httpStatus);
return?failResponse;
}
}
然后在认证服务器配置类中注入自定义异常翻译类
@Override
public?void?configure(AuthorizationServerEndpointsConfigurer?endpoints)?throws?Exception?{
//如果需要使用 refresh_token 模式则需要注入 userDetailService
endpoints
.authenticationManager(this.authenticationManager)
.userDetailsService(userDetailService)
//????????????????注入 tokenGranter
.tokenGranter(tokenGranter);
//注入自定义的 tokenservice,如果不使用自定义的 tokenService 那么就需要将 tokenServce 里的配置移到这里
//????????????????.tokenServices(tokenServices());
//?自定义异常转换类
endpoints.exceptionTranslator(new?CustomWebResponseExceptionTranslator());
}
客户端异常
重写客户端认证过滤器,不使用默认的 OAuth2AuthenticationEntryPoint
处理异常
public?class?CustomClientCredentialsTokenEndpointFilter?extends?ClientCredentialsTokenEndpointFilter?{
private?final?AuthorizationServerSecurityConfigurer?configurer;
private?AuthenticationEntryPoint?authenticationEntryPoint;
public?CustomClientCredentialsTokenEndpointFilter(AuthorizationServerSecurityConfigurer?configurer)?{
this.configurer?=?configurer;
}
@Override
public?void?setAuthenticationEntryPoint(AuthenticationEntryPoint?authenticationE 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 ntryPoint)?{
super.setAuthenticationEntryPoint(null);
this.authenticationEntryPoint?=?authenticationEntryPoint;
}
@Override
protected?AuthenticationManager?getAuthenticationManager()?{
return?configurer.and().getSharedObject(AuthenticationManager.class);
}
@Override
public?void?afterPropertiesSet()?{
setAuthenticationFailureHandler((request,?response,?e)?->?authenticationEntryPoint.commence(request,?response,?e));
setAuthenticationSuccessHandler((request,?response,?authentication)?->?{
});
}
}
在认证服务器注入异常处理逻辑,自定义异常返回结果。(代码位于 AuthorizationServerConfig
)
@Bean
public?AuthenticationEntryPoint?authenticationEntryPoint()?{
return?(request,?response,?e)?->?{
response.setStatus(HttpStatus.UNAUTHORIZED.value());
ResultData<String>?resultData?=?ResultData.fail(ReturnCode.CLIENT_AUTHENTICATION_FAILED.getCode(),?ReturnCode.CLIENT_AUTHENTICATION_FAILED.getMessage());
WebUtils.writeJson(response,resultData);
};
}
修改认证服务器配置,注入自定义过滤器
@Override
public?void?configure(AuthorizationServerSecurityConfigurer?security)?throws?Exception?{
CustomClientCredentialsTokenEndpointFilter?endpointFilter?=?new?CustomClientCredentialsTokenEndpointFilter(security);
endpointFilter.afterPropertiesSet();
endpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint());
security.addTokenEndpointAuthenticationFilter(endpointFilter);
security
.authenticationEntryPoint(authenticationEntryPoint())
/?.allowFormAuthenticationForClients()/?//如果使用表单认证则需要加上
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
评论