- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SpringCloud Alibaba实战之 Oauth2认证服务器自定义异常由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
今天内容主要是解决一位粉丝提的问题:在使用 Spring Security OAuth2 时如何自定义认证服务器返回异常.
那么首先我们先以 Password模式为例看看在认证时会出现哪些异常情况.
授权模式错误 。
这里我们故意将授权模式 password 修改成 password1,认证服务器返回如下所示的异常 。
{ 。
"error": "unsupported_grant_type", 。
"error_description": "Unsupported grant type: password1" 。
} 。
密码错误 。
在认证时故意输错 username 或 password 会出现如下异常错误:
{ 。
"error": "invalid_grant", 。
"error_description": "Bad credentials" 。
} 。
客户端错误 。
在认证时故意输错 client_id 或 client 。
{ 。
"error": "invalid_client", 。
"error_description": "Bad client credentials" 。
} 。
上面的返回结 。
上面的返回结果很不友好,而且前端代码也很难判断是什么错误,所以我们需要对返回的错误进行统一的异常处理,让其返回统一的异常格式.
问题剖析 。
如果只关注解决方案,可以直接跳转到解决方案模块.
OAuth2Exception异常处理 。
在Oauth2认证服务器中认证逻辑最终调用的是 TokenEndpoint#postAccessToken()方法,而一旦认证出现 OAuth2Exception异常则会被 handleException()捕获到异常。如下图展示的是当出现用户密码异常时debug截图:
认证服务器在捕获到 OAuth2Exception后会调用 WebResponseExceptionTranslator#translate()方法对异常进行翻译处理.
默认的翻译处理实现类是 DefaultWebResponseExceptionTranslator,处理完成后会调用 handleOAuth2Exception()方法将处理后的异常返回给前端,这就是我们之前看到的异常效果.
处理方法熟悉Oauth2套路的同学应该知道了如何处理此类异常,就是「自定义一个异常翻译类让其返回我们需要的自定义格式,然后将其注入到认证服务器中。」 。
但是这种处理逻辑只能解决 OAuth2Exception异常,即前言部分中的「授权模式异常」和「账号密码类的异常」,并不能解决我们客户端的异常.
客户端异常处理 。
客户端认证的异常是发生在过滤器 ClientCredentialsTokenEndpointFilter上,其中有后置添加失败处理方法,最后把异常交给 OAuth2AuthenticationEntryPoint这个所谓认证入口处理。执行顺序如下所示:
然后跳转到父类的 AbstractOAuth2SecurityExceptionHandler#doHandle()进行处理:
最终由 DefaultOAuth2ExceptionRenderer#handleHttpEntityResponse()方法将异常输出给客户端 。
处理方法 。
通过上面的分析我们得知客户端的认证失败异常是过滤器 ClientCredentialsTokenEndpointFilter转交给 OAuth2AuthenticationEntryPoint得到响应结果的,既然这样我们就可以重写 ClientCredentialsTokenEndpointFilter然后使用自定义的 AuthenticationEntryPoint替换原生的 OAuth2AuthenticationEntryPoint,在自定义 AuthenticationEntryPoint处理得到我们想要的异常数据.
解决方案 。
为了解决上面这些异常,我们首先需要编写不同异常的错误代码:ReturnCode.java 。
OAuth2Exception异常 。
@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 authenticationEntryPoint) { 。
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()"); 。
} 。
此时需要删除 allowFormAuthenticationForClients()配置,否则自定义的过滤器不生效,至于为什么不生效大家看看源码就知道了.
测试 。
授权模式错误 。
账号密码错误 。
客户端错误 。
以上,希望对你有所帮助.
原文地址:https://mp.weixin.qq.com/s/JwDTdone_8DV7wlr_CWZpw 。
最后此篇关于SpringCloud Alibaba实战之 Oauth2认证服务器自定义异常的文章就讲到这里了,如果你想了解更多关于SpringCloud Alibaba实战之 Oauth2认证服务器自定义异常的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用 Tornado 与 twitter 等第三方进行身份验证。 我的登录处理程序看起来像这样 class AuthLoginHandler(BaseHandler, tornado.auth.
有没有一种真正的方法可以在 Pylons 中添加身份验证?我见过很多不同的方法,但大多数方法要么过时,要么过于复杂。是否有教程可以解释如何以良好而可靠的方式添加身份验证? 最佳答案 考虑使用 repo
RESTful 身份验证是什么意思,它是如何工作的?我在谷歌上找不到很好的概述。我唯一的理解是您在 URL 中传递了 session key (记住),但这可能是非常错误的。 最佳答案 如何在 RES
我正在考虑在基于插件的系统中实现安全性的多种方式。现在,当我说“安全”时,我的意思是: a) 插件系统的开发人员如何确保插件在核心平台上的使用是安全的。b) 插件开发人员如何确保在其平台上使用的插件是
我正在使用 WCF Webhttp 服务。我创建了一堆服务,剩下的就是放入用户身份验证... 问题 与其余架构风格保持一致,我是否应该针对用户 db 验证每个服务调用。 如果是这样,我应该在每次调用服
假设我想对 Mifare Classic 进行身份验证。 我如何知道要发送到卡的确切类型的 APDU? 例子。 这段代码: bcla = 0xFF; bins = 0x86; bp1 = 0x0;
我通过在文件 xyz.php 中编写以下代码登录到网站。当我运行这个文件时,我会登录到 moodle 网站。有什么方法可以像下面的登录代码一样注销吗? $user = authenticate_use
我有一个应用程序可以匿名访问除几个之外的所有 xpages。我需要强制用户登录这些 xpages。是使用 beforepageload 事件来检查用户登录页面并将其重定向到正确的方式还是有更好的方法?
我想用 ember.js 实现身份验证。 因此,当应用程序启动时,在路由器处理请求的 url 之前,我想检查用户状态。如果用户未通过身份验证,我想保存请求的 url 并重定向到特定的 url (/lo
您如何执行 jQuery Ajax 调用并在发送请求之前对调用进行身份验证? 我还没有登录所以必须进行身份验证。安全不是任何人都可以访问的问题,只需要进行身份验证。它只是基本的 http 身份验证,您
我尝试使用找到的 swift 代码 here在网站上找到here ,但响应是带有两个错误的 html 代码:“您必须输入密码!”和“您必须输入用户名!”我是 NSURLSession 的新手,并尝试更
我正在尝试连接到 Visa Direct API,但我没有通过基本的 SSL 证书认证,这是我的代码: import requests headers = { 'Content
我正在用 tornado 在 python 中开发一个 REST API,我将实现身份验证和授权,试图避免锁定到其他大项目,即 django。我也在通过论坛和 SO 环顾四周,我喜欢一个可能适合的解决
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭10
如何在 Android 中通过 HTTP 进行身份验证? 最佳答案 我非常难以在 Android 中通过 HTTP 进行身份验证,因为在浏览器(Web 和 Android native )中它工作完美
我有一些关于登录和 session 的问题。我有这段代码: 数据库查询: login: function(req,callback) { var query = 'SELECT id FROM
我开始使用 Swift 开发 iOS 应用。现在我正处于需要创建登录系统的部分。但是,我们需要人们提供的 LinkedIn 信息。 我如何在 iOS 中使用 OAuth2 API 来实现这一点? 我已
如果没有找到用户,问题出在每个 $routeChangeStart 上,如果我只输入 url,它仍然会引导我访问页面。 现在我已经在服务器上重写了规则。 Options +FollowSymlinks
简单代码 require 'net/http' url = URI.parse('get json/other data here [link]') req = Net::HTTP::Get.new(
参考文档: https://docs.sonarqube.org/latest/instance-administration/security/ 概述 SonarQube具有
我是一名优秀的程序员,十分优秀!