前言

spring-security5 oauth 开箱既用,认证时返回的是oauth2 标准的返回值

先来看看,默认的返回值

## 未认证
{"error": "unauthorized","error_description": "Full authentication is required to access this resource"
}
## 认证失败
{
"error": "invalid_client",
"error_description": "Bad client credentials"
}## 认证成功
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6IndlYmFwcCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sIkF1dGhvciI6InhpYW95YW8iLCJleHAiOjE1NjEwMjYxNDAsImF1dGhvcml0aWVzIjpbIlJPTEVfVEVTVCIsIlJPTEVfT0FVVEhfQURNSU4iXSwianRpIjoiYzhlMTA3YTItYWFlZS00NWNhLTk1NWYtM2UyZDgwZjhlZmM2IiwiY2xpZW50X2lkIjoid2ViYXBwIiwidGltZXN0YW1wIjoiMTU2MTAxODk0MDEwOCJ9.VgL4voycGdn4Fm_Ij3ZeAc9Rxdsmb_IXR14lgtJh1KE",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6IndlYmFwcCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImM4ZTEwN2EyLWFhZWUtNDVjYS05NTVmLTNlMmQ4MGY4ZWZjNiIsIkF1dGhvciI6InhpYW95YW8iLCJleHAiOjE1NjIzMTQ5NDAsImF1dGhvcml0aWVzIjpbIlJPTEVfVEVTVCIsIlJPTEVfT0FVVEhfQURNSU4iXSwianRpIjoiMTRkNmQyMmMtZjc4OS00YzdlLTk0YjAtNTliYzhmYjlmY2NiIiwiY2xpZW50X2lkIjoid2ViYXBwIiwidGltZXN0YW1wIjoiMTU2MTAxODk0MDEwOCJ9.SOch9UKE078fRSxHYDZzXVTelVH3gpFOZUzM3KelKrk",
"expires_in": 7199,
"scope": "all",
"Author": "xiaoyao",
"clientId": "webapp",
"timestamp": "1561018940108",
"jti": "c8e107a2-aaee-45ca-955f-3e2d80f8efc6"
}

然而,这些虽是标准协议返回字段,公开给第三方做接口是没啥问题,但这个也会给我们前端去使用,这时候就会对前端造成一定的麻烦,在业务层,前端,一般会写一个拦截器,去通过一个code 或status字段,进行拦截,而认证阶段返回值就不统一了,所以我希望对于整个系统都是的,即看一下下面的期望结果的例子:

// code,msg,data 三个是我们与前端协定的整个系统中的返回值
# 未认证
{
"msg": "token不正确或已过期",
"code": "401",
"data": "Full authentication is required to access this resource",
// 下面两个是原始返回值
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}## 服务器错误{
"error": "invalid_request",
"code": 400,
"msg": "Internal Server Error",
"error_description": "Internal Server Error",
"data": ""
}// 登陆成功
{
"code": "200",
"msg": "success",
"data":{"access_token":         "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6IndlYmFwcCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sIkF1dGhvciI6InhpYW95YW8iLCJleHAiOjE1NjEwMjYxNDAsImF1dGhvcml0aWVzIjpbIlJPTEVfVEVTVCIsIlJPTEVfT0FVVEhfQURNSU4iXSwianRpIjoiYzhlMTA3YTItYWFlZS00NWNhLTk1NWYtM2UyZDgwZjhlZmM2IiwiY2xpZW50X2lkIjoid2ViYXBwIiwidGltZXN0YW1wIjoiMTU2MTAxODk0MDEwOCJ9.VgL4voycGdn4Fm_Ij3ZeAc9Rxdsmb_IXR14lgtJh1KE",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6IndlYmFwcCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImM4ZTEwN2EyLWFhZWUtNDVjYS05NTVmLTNlMmQ4MGY4ZWZjNiIsIkF1dGhvciI6InhpYW95YW8iLCJleHAiOjE1NjIzMTQ5NDAsImF1dGhvcml0aWVzIjpbIlJPTEVfVEVTVCIsIlJPTEVfT0FVVEhfQURNSU4iXSwianRpIjoiMTRkNmQyMmMtZjc4OS00YzdlLTk0YjAtNTliYzhmYjlmY2NiIiwiY2xpZW50X2lkIjoid2ViYXBwIiwidGltZXN0YW1wIjoiMTU2MTAxODk0MDEwOCJ9.SOch9UKE078fRSxHYDZzXVTelVH3gpFOZUzM3KelKrk",
"expires_in": 7199,
"scope": "all",
"Author": "xiaoyao",
"clientId": "webapp",
"timestamp": "1561018940108",
"jti": "c8e107a2-aaee-45ca-955f-3e2d80f8efc6"
}
}

知道自己希望想要什么,才好着手去撸代码

正文

这里面要分两步走,因为资源服务 和认证服务中是不一样的(刚开始做的我以为是一样的,后开跟了半天的源代码,才走出了这个坑)默认的主要有两个类`OAuth2AuthenticationEntryPoint` 和 `DefaultWebResponseExceptionTranslator`

//资源服务上,默认是交给这个类来处理的,包括未认证的,和错误的token
//认证服务器上未认证的也是这个
`OAuth2AuthenticationEntryPoint` //认证服务器上,上面的类不够用了,因为在security的过滤器中到处出现了
private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
和
private WebResponseExceptionTranslator exceptionTranslator = new DefaultWebResponseExceptionTranslator();
// 认证时产生的异常交给了这个类处理返回结果
`DefaultWebResponseExceptionTranslator`

先来看资源服务吧,这个比较简单

首先自定义一个`AuthenticationEntryPoint`

public class CustomAuthenticationEntryPoint extends OAuth2AuthenticationEntryPoint {private WebResponseExceptionTranslator<?> exceptionTranslator = new DefaultWebResponseExceptionTranslator();@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {//  super  ()  //doHandle(request, response, e)// log.debug("token 验证失败处理器")BaseResult<Object> res = new BaseResult<>();res.setCode(HttpStatus.UNAUTHORIZED.value());ResponseEntity<?> result = null;Map<String,String> resp = new HashMap<> (5);try {result = exceptionTranslator.translate(e);result = enhanceResponse(result, e);// 这里用的guava切分字符串转map,但不能直接返回赋值给 result ,不多做解释,跟踪一下源码就知道Map<String, String> split = Splitter.on(",").trimResults().trimResults(CharMatcher.is('\"')).withKeyValueSeparator("=\"").split(result.getBody().toString());// 不去改变原来父类里面返回的属性和值split.forEach((x,y) ->resp.put(x.trim(), y));} catch (Exception ex) {log.error("结果解析异常", ex);}resp.put("code", res.getCode()+"");resp.put("msg", "token不正确或已过期");resp.put("data",e.getMessage());HttpResponseUtil.writeResult(response, resp, HttpStatus.UNAUTHORIZED);}}

然后在资源费器的配置中配置即可

public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {@Autowiredprivate BaseAuthenticationConfig baseAuthenticationConfig;@Autowired(required = false)private AuthenticationEntryPoint authenticationEntryPoint;@Overridepublic void configure(HttpSecurity http) throws Exception {log.debug("Using ResourceServerConfiguration configure(HttpSecurity). " );baseAuthenticationConfig.configure(http);http.authorizeRequests().antMatchers(baseAuthenticationConfig.getIgnoreUrl()).permitAll().antMatchers("/login","/error","/oauth/token","/process/login","/logout","/login.html").permitAll()// .antMatchers("/**").authenticated().antMatchers("/sys/sys-user/info").authenticated().and().csrf().disable();}// 在这儿配@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {// 配置认证失败处理器if(authenticationEntryPoint != null){resources.authenticationEntryPoint(authenticationEntryPoint);}}}

认证服务器,稍微麻烦点

首先将自定义的 `AuthenticationEntryPoint`在http config中配置上

public void configure(HttpSecurity http) throws Exception {http.formLogin().loginPage("/login").loginProcessingUrl("/user/login").successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and().authorizeRequests().antMatchers("/login","/user/login","/user/logout","/oauth/token").permitAll().and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()//  这里设置的 只是用户没有登录的 情况下 没有token 的情况下,异常给下面的处理.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);}

好了在登录时认证失败会产生各种异常,但最有都有一个`ExceptionTranslationFilter`处理,这个是spring security的基础知识(插张图)

这个是访问认证服务器 资源的时候,还是交给自定义的AuthenticationEntryPoint 处理的

看一下登陆的时候

登陆失败

-- 未完 待续,主要原因在用户通过授权码登陆异常时没有走自定义的异常处理类

Spring Security5 Oauth2 自定义 OAuth2 Exception相关推荐

  1. Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)并与UsernamePassword登录关联解决方案

    前文:Spring Security OAuth2--自定义OAuth2第三方登录(Gitee) Maven 主要 <!--Spring Security--><dependency ...

  2. Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)

    官方文档 https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-custom-pr ...

  3. 如何使用okta作为认证方配置Spring Boot 2 Security5集成的OAuth2登录到我们自己的工程项目------范例3

    本篇范例在范例2的基础上持续集成扩展 注册账号的地址如下: https://developer.okta.com/signup/ 注册成功要求你用临时密码(发送到你邮箱的)激活你的注册账号 此网站会分 ...

  4. 使用Spring Boot 2使用OAuth2和不透明令牌进行集中授权

    如果您正在寻找JWT实施,请点击此链接 本指南逐步介绍了使用Spring Boot 2创建集中式身份验证和授权服务器的过程,还将提供演示资源服务器. 如果您不熟悉OAuth2,建议您阅读此书. 先决条 ...

  5. 使用Spring Boot 2通过OAuth2和JWT进行集中授权

    本指南逐步介绍了使用Spring Boot 2创建集中式身份验证和授权服务器的过程,还将提供演示资源服务器. 如果您不熟悉OAuth2,建议您阅读此书. 先决条件 JDK 1.8 文本编辑器或您喜欢的 ...

  6. Spring Boot Security 整合 OAuth2 设计安全API接口服务

    OAuth2概述 oauth2根据使用场景不同,分成了4种模式 授权码模式(authorization code) 简化模式(implicit) 密码模式(resource owner passwor ...

  7. (附源码)Spring Boot 框架整合 OAuth2 实现单点登录 SSO 详细完整源码教程!

    1.  前言 技术这东西吧,看别人写的好像很简单似的,到自己去写的时候就各种问题,"一看就会,一做就错".网上关于实现SSO的文章一大堆,但是当你真的照着写的时候就会发现根本不是那 ...

  8. Spring Security(5) 整合OAuth2

    文章目录 一.前言 二.什么是OAuth2? 三.应用场景 四.三部分 五.四种授权模式 1. 授权码模式(authorization code) 2. 简化模式(implicit) 3. 密码模式( ...

  9. Spring Security 5.x+OAuth2.0+OIDC1.0

    Spring Security+OAuth2.0+OIDC1.0 文章目录 Spring Security+OAuth2.0+OIDC1.0 前言 一.准备工作 1.Spring Security相关 ...

最新文章

  1. 六条规则让你的ML模型部署的更快
  2. ubuntu16.04在英文状态下安装中文语言包的过程(法一:图形界面的方式) 以及 安装中文语言包后无法选择汉语问题的解决
  3. 【转载】python3安装scrapy之windows32位爬坑
  4. leetcode868
  5. 人眼中亮斑的检测、定位和去除(3)
  6. Yearning v1.4.2 发布,SQL审核平台
  7. ppt倒计时_年终会议做一个这样的倒计时PPT,保证惊艳全场!1分钟就能学会
  8. 图书馆管理系统项目思路
  9. openGauss 正式开源并成立开源社区
  10. sql 系统 存储过程的使用方法 转载
  11. 【干货】统计学思维导图
  12. 架构之路(五):忘记数据库
  13. Cartesian k-means论文理解
  14. Atitit.软件硕士  博士课程 一览表 attilax 总结
  15. layui radio 赋初始值
  16. win环境sftp软件_Windows环境下使用bitvise架构sftp服务器
  17. 【Get Up&Move】MMD镜头+动作打包下载.zip
  18. 什么是手机号码姓名实名认证 手机号码查姓名 手机号实名认证API
  19. epub是什么文件?epub文件怎么打开?
  20. 埋石图根点lisp代码_速腾矿图 用户手册.pdf

热门文章

  1. 华为LAB实验室:0-Ubuntu搭建实验环境
  2. JavaScript面试真题
  3. Office WORD EXCEL批量查找和替换技巧实例
  4. Linux实验一报告
  5. 网易云歌词解析(配合audio标签实现本地歌曲播放,歌词同步)
  6. js网易云歌词解析处理,
  7. 简单,向MySql中存入图片
  8. 科学家研制出世界上第一个用木头制成的晶体管
  9. android opengles光照效果-散射光
  10. 蓝桥杯省赛模拟真题六