目录

  • 文章
  • 一、简介
    • 1.1 OAuth2.0协议角色
    • 1.2 SpringSecurityOAuth2.0
  • 二、认证流程
  • 三、授权服务器——代码实现
    • 3.1 主要依赖
    • 3.2 AuthorizationServer
      • 3.2.1 配置客户端详情信息
      • 3.2.2 配置令牌的服务端点及令牌管理服务
      • 3.2.3 配置令牌服务端点的安全约束
      • 3.2.4 总结
  • 三、授权服务器——测试
    • 3.1 授权码模式示例
      • 申请授权
      • 同意授权
      • 拒绝授权
      • 申请令牌
    • 3.2 密码模式示例
      • 申请令牌
    • 3.3 简单授权模式示例
      • 申请授权
      • 同意授权后直接返回令牌
    • 3.4 客户端授权模式
      • 申请令牌
  • 四、资源服务器——代码实现
    • 4.1 OrderController定义访问的资源服务的请求
    • 4.2 ResourceServer资源服务配置
  • 五、资源服务器——测试
    • 5.1 不带令牌请求资源服务
    • 5.2 申请授权码 用户同意授权
    • 5.3 携带授权码 申请令牌
    • 5.4 校验令牌
    • 5.5 请求资源服务 校验令牌
      • 5.5.1 以zs申请的令牌访问资源
      • 5.5.2 以ls申请的令牌访问资源
    • 401 Unauthorized 报错
  • 源码
  • 附录

文章

分布式系统认证解决方案SpringSecurityOAuth2.0(一)认证授权
分布式系统认证解决方案SpringSecurityOAuth2.0(二)分布式系统认证流程分析与实现
分布式系统认证解决方案SpringSecurityOAuth2.0(三)资源服务器使用Redis令牌、JWT令牌认证及RSA非对称加密算法
分布式系统认证解决方案SpringSecurityOAuth2.0(四)整合网关认证授权

一、简介

最终实现目标:

OAuth(开放授权)2.0是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用。比如:用户(资源拥有者)授权 王者荣耀(第三方应用,也称为客户端)允许访问用户在微信(资源服务器)的个人信息,从而登录王者荣耀。

OAuth协议目前已经发展到了2.0版本,1.0版本过于复杂,2.0版本已经得到广泛应用。

1.1 OAuth2.0协议角色

  1. 客户端,需要通过资源拥有者的授权去请求资源服务器。
  2. 资源拥有者,通常为用户,即该资源拥有者。
  3. 授权服务器,也称认证服务器,认证成功后会给客户端发送令牌,作为客户端访问资源服务器的凭证,如微信的认证服务器。
  4. 资源服务器,存储资源的服务器,例如微信存储的用户信息。

1.2 SpringSecurityOAuth2.0

SpringSecurityOAuth2是对OAuth2的一种实现,并且跟SpringSecurity相辅相成,与SpringCloud体系的集成也十分的方便,我们使用它来设计分布式认证授权解决方案。

OAuth2.0服务提供方涵盖两个服务,即授权服务(Authorization Server,也叫认证服务)和资源服务(Resource Server),使用SpringSecurityOAuth2的时候可以在同一个应用程序中来实现,也可以选择建立使用同一个授权服务的多个资源服务。

  1. 授权服务 AuthorizationServer
    授权服务(Authorization Server)应包含对接入端以及登入用户的合法性进行验证并颁发Token等功能,对令牌的请求端点由SpringMVC控制器进行实现,下面是配置一个认证服务必须要实现的endpoints:
    Authorizationendpoint 服务于认证请求。默认 URL:/oauth/authorize。
    TokenEndpoint 服务于访问令牌的请求。默认 URL:/oauth/token 。
  2. 资源服务 ResourceServer
    资源服务(Resource Server),应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等。
    OAuth2AuthenticationProcessingFilter 用来对请求给出的身份令牌解析鉴权。

二、认证流程

  1. 客户端请求授权服务进行授权认证。
  2. 授权认证通过后由授权服务颁发令牌Token
  3. 客户端携带令牌Token请求资源服务
  4. 资源服务校验令牌的合法性,合法即返回资源信息。

但并不是所有的客户端都可以访问认证服务器,认证服务器会给客户端提供一个身份:client_id(客户端标识)和client_secret(客户端秘钥)。
所以认证服务器需要对资源拥有者客户端两个角色进行校验。需要确认:

  1. 是否是本人授权
  2. 是否是合法的客户端。

以授权码模式为例,以下是授权码模式认证流程:

三、授权服务器——代码实现

授权服务器的作用就是对客户端进行认证授权,让其有资格访问用户的资源服务。

3.1 主要依赖

     <!-- SpringSecurity 权限 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--spring-security-oauth2 --><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId></dependency><!--spring-security-oauth2-autoconfigure--><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId></dependency>

3.2 AuthorizationServer

新建AuthorizationServer类需要继承AuthorizationServerConfigurerAdapter

添加@Configuration@EnableAuthorizationServer注解。
实现AuthorizationServerConfigurerAdapter类的三个方法:

3.2.1 配置客户端详情信息

配置客户端详情信息,在此处配置的客户端详细信息,来申请授权或者申请令牌的客户端才能被识别。

  1. resourceIds资源列表和scope允许授权的范围都是自己定义的标识。
  2. autoApprove自动批准设置为false会跳转到手动授权页面,有用户决定是否授权。
  3. authorizedGrantTypes 表示该客户端的授权类型:包括authorization_code授权码模式、password密码模式、client_credentials客户端模式、implicit隐式授权模式以及refresh_token更新token。
    注意:只有客户端在这里配置的授权类型,在申请令牌的时候才能使用对应的授权类型,比如:如果在配置c1客户端的客户端详细信息的时候没有配置密码授权模式,则在申请令牌的时候就不能使用密码模式。

3.2.2 配置令牌的服务端点及令牌管理服务

首先配置令牌管理服务,包括客户端详情服务、令牌存储策略等配置。

  1. 配置客户端详情服务是为了识别客户端的身份,因为并不是随便一个客户端都能来申请授权或者申请令牌,必须是配置到客户端详细服务中的客户端才可以。
  2. 配置令牌存储策略则是配置令牌是使用哪种方式存储。


然后需要配置令牌的服务端点包括认证管理器授权码服务令牌管理服务以及允许的令牌服务端口的请求方法为POST请求:

  1. 认证管理器:认证用户信息。
    认证管理器AuthorizationManager是在SpringSecurity的配置类中的,
    关于SpringSecurity的认证可以参考上一章:https://blog.csdn.net/DreamsArchitects/article/details/119777733

  1. 授权码服务:设置授权码模式的授权码如何存储。

  2. 令牌管理服务,将我们配置的令牌管理服务配置到令牌服务端点中。

令牌服务端点就是客户端来请求授权或者来申请令牌的地址:

configure(ClientDetailsServiceConfigurer clients) clients的pathMapping()方法用来配置端点的URL链接,
//这是框架默认的地址:
/oauth/authorize 授权端点
/oauth/token     令牌端点
/oauth/confirm_access  用户确认授权提交端点
/oauth/error     授权服务错误信息端点
/oauth/check_token 用于资源服务访问的令牌解析端点
/oauth/token_key  提供公有秘钥的端点,比如使用JWT令牌  采用RSA非对称加密方式

3.2.3 配置令牌服务端点的安全约束

上一步中我们配置了令牌服务端点,但是这些服务端点不是随便都可以请求的,需要配置一些安全约束:

3.2.4 总结

这里的配置可能有点乱,但是是有逻辑的:

  1. 既然要完成认证,它首先需要知道客户端信息从哪读取,所以需要配置客户端详细信息。
  2. 既然要颁发token,就必须定义token的相关endpoint,以及token如何存取及客户端支持哪些类型的token。
  3. 既然暴露了这些endpoint,就需要对这些endpoint加上安全约束。

三、授权服务器——测试

3.1 授权码模式示例

申请授权

在浏览器访问:http://localhost:8081/oauth2/oauth/authorize?client_id=c1&client_secret=secret&response_type=code&scope=all&redirect_uri=http://www.baidu.com,申请用户授权。
然后跳转授权服务授权页面,此时需要登录认证授权服务。

客户端ID标识 客户端秘钥 授权模式 权限范围 重定向URL
client_id client_secret response_type scope redirect_uri
c1 secret code all http://www.baidu.com

如下图所示:

登录认证成功后跳转授权页面,如下图所示:

同意授权

点击同意授权浏览器跳转重定向页面:https://www.baidu.com/?code=jUShMQ
在重定向的路径中返回授权码信息,如下图所示,code即为授权服务返回的授权码

拒绝授权

页面跳转至重定向页面,在重定向路径中显示用户拒绝授权信息:https://www.baidu.com/?error=access_denied&error_description=User%20denied%20access,如下图所示:

申请令牌

在上一步用户同意授权后,客户端获得授权服务器返回的授权码,使用授权码去授权服务器申请令牌access_tokengrant_type指定为authorization_code(授权码模式)
请求为POST方式。

客户端ID标识 客户端秘钥 授权模式 授权码 重定向URL
client_id client_secret grant_type code redirect_uri
c1 secret authorization_code HnqLzS http://www.baidu.com

返回的信息包含:
access_token为令牌、
token_type为令牌类型、
refresh_token为更新令牌的token,更新令牌时用到、
expires_in为令牌过期时间,单位为秒、
scope为授权范围。

3.2 密码模式示例

使用密码模式的话就不需要申请授权了,直接申请令牌,需要指定grant_typepassword,携带usernamepassword字段。

申请令牌

3.3 简单授权模式示例

申请授权

简单模式就是在申请授权的时候,如果授权服务器认证成功,则直接返回令牌:
简单模式请求申请授权接口:http://localhost:8081/oauth2/oauth/authorize?client_id=c1&client_secret=secret&response_type=token&scope=all&redirect_uri=http://www.baidu.com
需要将response_type指定为token

同意授权后直接返回令牌

令牌access_token包含在重定向的地址中:https://www.baidu.com/#access_token=fd531d73-7030-401f-b307-99301888feaf&token_type=bearer&expires_in=7199

3.4 客户端授权模式

申请令牌

客户端授权模式只需要客户端的ID和客户端秘钥进行申请令牌:
需要将grant_type改为client_credentials

客户端ID标识 客户端秘钥 授权模式
client_id client_secret grant_type
c1 secret client_credentials

四、资源服务器——代码实现

4.1 OrderController定义访问的资源服务的请求

OrderController定义访问的资源服务的请求:/order/test

4.2 ResourceServer资源服务配置

ResourceServer资源服务配置:
@EnableResourceServer注解到一个@Configuration配置类上,并且需要继承ResourceServerConfigurerAdapter类重写其中方法:
(@EnableResourceServer 注解自动增加了一个类型为OAuth2AuthorizationProcessingFilter的过滤器链)

***ResourceServerSecurityConfigurer***中主要包括:

  1. tokenService:ResourceServerTokenService类的实例,用来实现令牌服务。
  2. tokenStore:TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选。
  3. resourceId:这个资源服务的ID,属性可选,推荐设置并在授权服务中验证。
  4. 其他拓展属性例如tokenExtractor令牌提取器用来提取请求中的令牌。

验证token:
ResourceServerTokenService是组成授权服务的另一半,如果你的授权服务和资源服务在同一个应用程序,可以使用DefaultTokenService,这样就不用考虑实现所有必要的接口的一致性问题。如果资源服务器是分开的,那么就必须确保能够有匹配授权服务提供的ResourceServerTokenService,它知道如何对令牌进行解码、
令牌解析方法:
使用DefaultTokenServices 在资源服务器本地配置令牌存储、解码、解析方式。
使用RemoteTokenServices 资源服务器通过HTTP请求解码令牌,每次都请求授权服务器端点/oauth/check_token

***HttpSecurity***配置这个雨SpringSecurity类似:

  1. 请求匹配器,用来设置需要进行保护的资源路径,默认的情况是保护资源服务的全部路径。
  2. 通过http.authorizeRequest()来设置受保护资源的访问规则。
  3. 其他的自定义权限保护规则通过HttpSecurity来进行配置

五、资源服务器——测试

启动授权服务和资源服务,客户端获得令牌后,可以拿着令牌去访问资源服务器,这个时候资源服务器会校验令牌的合法性。

5.1 不带令牌请求资源服务

如果没有令牌请求资源服务请求失败:

5.2 申请授权码 用户同意授权

申请授权:http://localhost:8081/oauth2/oauth/authorize?client_id=c1&client_secret=order&response_type=code&scope=all&redirect_uri=http://www.baidu.com

获得授权码:http://baidu.com/?code=nYPZQ5

5.3 携带授权码 申请令牌

5.4 校验令牌

授权服务器校验令牌端点:http://localhost:8081/oauth2/oauth/check_tokenPOST请求,响应中返回用户的身份信息及客户端id和权限范围等:

5.5 请求资源服务 校验令牌

请求资源服务需要携带token令牌,在请求头中,请求头Key为:Authorization ,请求头Value为:Bearer token值
注意:Bearer与token之间有空格隔开。

由于我们定义的资源方法需要有ADMIN的角色认证,所以我们分别使用zsls申请的令牌请求资源服务:

5.5.1 以zs申请的令牌访问资源

zsADMIN角色,可以请求资源服务成功:

5.5.2 以ls申请的令牌访问资源

lsUSER角色,则不能访问资源成功:

401 Unauthorized 报错

后台抛异常,前端页面浏览器显示状态码500,内部错误。是不准确的。但事实上是401错误
因后端抛出了异常导致。
原因是认证失败了,可能资源服务器和授权服务器两个配置的信息不对应,可能有以下几个问题:

  1. 资源ID不对。
  2. 客户端ID不对。
  3. 客户端秘钥不对(在授权服务器配置客户端详细信息的时候客户端秘钥使用了BCryptPasswordEncoder加密,而资源服务器解析令牌的时候不需要将客户端秘钥进行BCrypt编码)。

源码

代码已上传码云
https://gitee.com/L1692312138/spring-cloud-alibaba

附录

本编文章介绍了OAuth2.0的认证服务的流程和简单实现,下篇文章将介绍使用JWT令牌的形式来进行资源服务的认证;客户端详细信息、授权码、令牌这些信息如何存储在数据库中。

因为本文中的资源服务校验令牌是远程调用的授权服务的/oauth/check_token令牌服务端点,而使用JWT的形式,则不需要进行远程调用,JWT本身就包含了所有的认证信息。

分布式系统认证解决方案SpringSecurityOAuth2.0(二)分布式系统认证流程分析与实现相关推荐

  1. android6.0中app crash流程分析

    要根据这个流程分析一下如何在应用中截获系统的app crash弹框,然后做到更人性化 基于Android 6.0的源码剖析, 分析Android应用Crash是如何处理的. /frameworks/b ...

  2. android6.0源码分析之Camera API2.0下的初始化流程分析

    1.Camera2初始化的应用层流程分析 Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程.Camera2.0首先启动的是C ...

  3. Exynos4412 中断驱动开发(二)—— 中断处理流程分析

    前面已经学习了中断的注册过程,下面由一张流程图来看一下当中断发生时的处理流程: 中断发生之后处理流程 a -- 具体的CPU architecture相关模块进行现场保护,然后调用machine dr ...

  4. SpringBoot(十二)启动流程分析之创建应用上下文AnnotationConfigServletWebServerApplicationContext

    SpringBoot版本:2.1.1      ==>启动流程分析汇总 接上篇博客Spring Boot 2.1.1(十一)启动流程分析之设置系统属性spring.beaninfo.ignore ...

  5. Android 7.0 挂断电话流程分析

    1.图形显示 挂断电话分为本地挂断和远程对方挂断 2.本地挂断 1).点击按钮 先看按键的监听事件 CallCardFragment.java 中有对按钮的监听事件 @Overridepublic v ...

  6. 从0移植uboot (二) _uboot启动流程分析

    经过了上一篇的配置,我们已经执行make就可以编译出一个uboot.bin,但这还不够,首先,此时的uboot并不符合三星芯片对bootloader的格式要求,同时,此时的uboot.bin也没有结合 ...

  7. 从0移植uboot (二) _启动流程分析

    来源:Linux社区  作者:xiaojiang1025  : http://www.linuxidc.com/Linux/2017-02/141019.htm 经过了上一篇的配置,我们已经执行mak ...

  8. android6.0源码分析之Camera API2.0下的Capture流程分析

    前面分析preview的时候,当预览成功后,会使能ShutterButton,即可以进行拍照,定位到ShutterButton的监听事件为onShutterButtonClick方法: <cod ...

  9. mini2440 u-boot linux 内核启动,u-boot.2012.10——mini2440(二、启动流程分析)

    参考资料:https://blog.csdn.net/suiyuan19840208/article/details/7239949 https://blog.csdn.net/pugu12/arti ...

最新文章

  1. 三、新手Jupyter不会用,我十招教你盘她
  2. java pem,如何验证Java中的PEM格式证书
  3. 网络编程-TCP/IP协议栈-TCP协议
  4. 基于wincc的虚拟电梯设计_一文带你了解西门子整个虚拟调试与仿真软硬件体系...
  5. 达梦数据库查询数据库所有表名_达梦数据库的一些实用小SQL
  6. Java File类void deleteOnExit()方法(带示例)
  7. 实习期间的一些思考整理(3)2018.4.12~4.13
  8. 中小企业上ERP项目不可回避的9个基本问题
  9. 【Vue】—插槽的基本语法
  10. 116. cURL 简介(2)
  11. html中无序列表做成链接,Beautifulsoup从无序列表中提取文本和链接divulli(斯堪的纳维亚字符)...
  12. html自动补位的功能,js中位数不足自动补位扩展padLeft、padRight实现代码
  13. 简析JavaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序
  14. 5G到底什么时候来,以及,它究竟能给我们带来什么?
  15. 华为WeAutomate RPA产品首席规划师周为:企业数智化转型之路,RPA共创新价值
  16. 杨建荣的学习笔记排行榜(r2笔记100天)
  17. 迈阿密大学的计算机系咋样,迈阿密大学计算机科学专业
  18. python lambda 判断_Python lambda
  19. 【MPI编程】矩阵向量乘法--解法三(子矩阵块分解)【高性能计算】
  20. GitHub计算机书籍资源库,值得收藏

热门文章

  1. Java后端:html转pdf实战笔记
  2. 云原生时代下,微服务体系与 Serverless 架构的发展、治理与融合
  3. Python读写文件的七种模式(r,w,x,a,b,t,+)
  4. mysql初始设置_三 mysql 初始配置
  5. (LaTeX) Solved: 引用网页时出现的空格间距过大;网页链接的字体不符合要求
  6. 易语言-API 取窗口或者组件句柄的 屏幕坐标并限制区域 GetWindowRect ClipCursor getwindowrect GetClientRect WindowFromPoint
  7. NR数据库的物种注释
  8. linux 12541无监听程序,ORA-12541:TNS:无监听程序问题 解决办法
  9. 用Lombok项目减少样板代码(翻译自官方文档)
  10. 同步、异步、单工、双工、半双工有啥不同