分布式系统认证解决方案SpringSecurityOAuth2.0(二)分布式系统认证流程分析与实现
目录
- 文章
- 一、简介
- 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 SpringSecurityOAuth2.0
SpringSecurityOAuth2
是对OAuth2
的一种实现,并且跟SpringSecurity相辅相成,与SpringCloud体系的集成也十分的方便,我们使用它来设计分布式认证授权解决方案。
OAuth2.0
服务提供方涵盖两个服务,即授权服务
(Authorization Server,也叫认证服务)和资源服务
(Resource Server),使用SpringSecurityOAuth2
的时候可以在同一个应用程序中来实现,也可以选择建立使用同一个授权服务的多个资源服务。
授权服务 AuthorizationServer
授权服务(Authorization Server)应包含对接入端以及登入用户的合法性进行验证并颁发Token等功能,对令牌的请求端点由SpringMVC控制器进行实现,下面是配置一个认证服务必须要实现的endpoints:
Authorizationendpoint 服务于认证请求。默认 URL:/oauth/authorize。
TokenEndpoint 服务于访问令牌的请求。默认 URL:/oauth/token 。资源服务 ResourceServer
资源服务(Resource Server),应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等。
OAuth2AuthenticationProcessingFilter
用来对请求给出的身份令牌解析鉴权。
二、认证流程
客户端
请求授权服务
进行授权认证。- 授权认证通过后由
授权服务
颁发令牌Token
。 客户端
携带令牌Token
请求资源服务
。资源服务
校验令牌
的合法性,合法即返回资源信息。
但并不是所有的客户端都可以访问认证服务器,认证服务器会给客户端提供一个身份:client_id
(客户端标识)和client_secret
(客户端秘钥)。
所以认证服务器
需要对资源拥有者
和客户端
两个角色进行校验。需要确认:
- 是否是本人授权
- 是否是合法的客户端。
以授权码模式为例,以下是授权码模式
认证流程:
三、授权服务器——代码实现
授权服务器的作用就是对客户端进行认证授权,让其有资格访问用户的资源服务。
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 配置客户端详情信息
配置客户端详情信息,在此处配置的客户端详细信息,来申请授权或者申请令牌的客户端才能被识别。
resourceIds
资源列表和scope
允许授权的范围都是自己定义的标识。autoApprove
自动批准设置为false会跳转到手动授权页面,有用户决定是否授权。- authorizedGrantTypes 表示该客户端的授权类型:包括
authorization_code
授权码模式、password
密码模式、client_credentials
客户端模式、implicit
隐式授权模式以及refresh_token
更新token。
注意:只有客户端在这里配置的授权类型,在申请令牌的时候才能使用对应的授权类型,比如:如果在配置c1客户端的客户端详细信息的时候没有配置密码授权模式,则在申请令牌的时候就不能使用密码模式。
3.2.2 配置令牌的服务端点及令牌管理服务
首先配置令牌管理服务
,包括客户端详情服务、令牌存储策略等配置。
- 配置客户端详情服务是为了识别客户端的身份,因为并不是随便一个客户端都能来申请授权或者申请令牌,必须是配置到客户端详细服务中的客户端才可以。
- 配置令牌存储策略则是配置令牌是使用哪种方式存储。
然后需要配置令牌的服务端点包括认证管理器
、授权码服务
、令牌管理服务
以及允许的令牌服务端口的请求方法
为POST请求:
- 认证管理器:认证用户信息。
认证管理器AuthorizationManager
是在SpringSecurity的配置类中的,
关于SpringSecurity的认证可以参考上一章:https://blog.csdn.net/DreamsArchitects/article/details/119777733
授权码服务:设置授权码模式的授权码如何存储。
令牌管理服务,将我们配置的令牌管理服务配置到令牌服务端点中。
令牌服务端点就是客户端来请求授权或者来申请令牌的地址:
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 总结
这里的配置可能有点乱,但是是有逻辑的:
- 既然要完成认证,它首先需要知道客户端信息从哪读取,所以需要配置客户端详细信息。
- 既然要颁发token,就必须定义token的相关endpoint,以及token如何存取及客户端支持哪些类型的token。
- 既然暴露了这些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_token
,grant_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_type
为password
,携带username
和password
字段。
申请令牌
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***中主要包括:
- tokenService:ResourceServerTokenService类的实例,用来实现令牌服务。
- tokenStore:TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选。
- resourceId:这个资源服务的ID,属性可选,推荐设置并在授权服务中验证。
- 其他拓展属性例如tokenExtractor令牌提取器用来提取请求中的令牌。
验证token:
ResourceServerTokenService是组成授权服务的另一半,如果你的授权服务和资源服务在同一个应用程序,可以使用DefaultTokenService,这样就不用考虑实现所有必要的接口的一致性问题。如果资源服务器是分开的,那么就必须确保能够有匹配授权服务提供的ResourceServerTokenService,它知道如何对令牌进行解码、
令牌解析方法:
使用DefaultTokenServices 在资源服务器本地配置令牌存储、解码、解析方式。
使用RemoteTokenServices 资源服务器通过HTTP请求解码令牌,每次都请求授权服务器端点/oauth/check_token
。
***HttpSecurity***配置这个雨SpringSecurity类似:
- 请求匹配器,用来设置需要进行保护的资源路径,默认的情况是保护资源服务的全部路径。
- 通过http.authorizeRequest()来设置受保护资源的访问规则。
- 其他的自定义权限保护规则通过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_token
,POST
请求,响应中返回用户的身份信息及客户端id和权限范围等:
5.5 请求资源服务 校验令牌
请求资源服务需要携带token令牌,在请求头中,请求头Key为:Authorization
,请求头Value为:Bearer token值
。
注意:Bearer与token之间有空格隔开。
由于我们定义的资源方法需要有ADMIN
的角色认证,所以我们分别使用zs
和ls
申请的令牌请求资源服务:
5.5.1 以zs申请的令牌访问资源
zs
为ADMIN
角色,可以请求资源服务成功:
5.5.2 以ls申请的令牌访问资源
ls
为USER
角色,则不能访问资源成功:
401 Unauthorized 报错
后台抛异常,前端页面浏览器显示状态码500
,内部错误。是不准确的。但事实上是401
错误
因后端抛出了异常导致。
原因是认证失败了,可能资源服务器和授权服务器两个配置的信息不对应,可能有以下几个问题:
- 资源ID不对。
- 客户端ID不对。
- 客户端秘钥不对(在授权服务器配置客户端详细信息的时候客户端秘钥使用了BCryptPasswordEncoder加密,而资源服务器解析令牌的时候不需要将客户端秘钥进行BCrypt编码)。
源码
代码已上传码云
https://gitee.com/L1692312138/spring-cloud-alibaba
附录
本编文章介绍了OAuth2.0的认证服务的流程和简单实现,下篇文章将介绍使用JWT
令牌的形式来进行资源服务的认证;客户端详细信息、授权码、令牌这些信息如何存储在数据库中。
因为本文中的资源服务校验令牌是远程调用的授权服务的/oauth/check_token
令牌服务端点,而使用JWT
的形式,则不需要进行远程调用,JWT本身就包含了所有的认证信息。
分布式系统认证解决方案SpringSecurityOAuth2.0(二)分布式系统认证流程分析与实现相关推荐
- android6.0中app crash流程分析
要根据这个流程分析一下如何在应用中截获系统的app crash弹框,然后做到更人性化 基于Android 6.0的源码剖析, 分析Android应用Crash是如何处理的. /frameworks/b ...
- android6.0源码分析之Camera API2.0下的初始化流程分析
1.Camera2初始化的应用层流程分析 Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程.Camera2.0首先启动的是C ...
- Exynos4412 中断驱动开发(二)—— 中断处理流程分析
前面已经学习了中断的注册过程,下面由一张流程图来看一下当中断发生时的处理流程: 中断发生之后处理流程 a -- 具体的CPU architecture相关模块进行现场保护,然后调用machine dr ...
- SpringBoot(十二)启动流程分析之创建应用上下文AnnotationConfigServletWebServerApplicationContext
SpringBoot版本:2.1.1 ==>启动流程分析汇总 接上篇博客Spring Boot 2.1.1(十一)启动流程分析之设置系统属性spring.beaninfo.ignore ...
- Android 7.0 挂断电话流程分析
1.图形显示 挂断电话分为本地挂断和远程对方挂断 2.本地挂断 1).点击按钮 先看按键的监听事件 CallCardFragment.java 中有对按钮的监听事件 @Overridepublic v ...
- 从0移植uboot (二) _uboot启动流程分析
经过了上一篇的配置,我们已经执行make就可以编译出一个uboot.bin,但这还不够,首先,此时的uboot并不符合三星芯片对bootloader的格式要求,同时,此时的uboot.bin也没有结合 ...
- 从0移植uboot (二) _启动流程分析
来源:Linux社区 作者:xiaojiang1025 : http://www.linuxidc.com/Linux/2017-02/141019.htm 经过了上一篇的配置,我们已经执行mak ...
- android6.0源码分析之Camera API2.0下的Capture流程分析
前面分析preview的时候,当预览成功后,会使能ShutterButton,即可以进行拍照,定位到ShutterButton的监听事件为onShutterButtonClick方法: <cod ...
- mini2440 u-boot linux 内核启动,u-boot.2012.10——mini2440(二、启动流程分析)
参考资料:https://blog.csdn.net/suiyuan19840208/article/details/7239949 https://blog.csdn.net/pugu12/arti ...
最新文章
- 三、新手Jupyter不会用,我十招教你盘她
- java pem,如何验证Java中的PEM格式证书
- 网络编程-TCP/IP协议栈-TCP协议
- 基于wincc的虚拟电梯设计_一文带你了解西门子整个虚拟调试与仿真软硬件体系...
- 达梦数据库查询数据库所有表名_达梦数据库的一些实用小SQL
- Java File类void deleteOnExit()方法(带示例)
- 实习期间的一些思考整理(3)2018.4.12~4.13
- 中小企业上ERP项目不可回避的9个基本问题
- 【Vue】—插槽的基本语法
- 116. cURL 简介(2)
- html中无序列表做成链接,Beautifulsoup从无序列表中提取文本和链接divulli(斯堪的纳维亚字符)...
- html自动补位的功能,js中位数不足自动补位扩展padLeft、padRight实现代码
- 简析JavaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序
- 5G到底什么时候来,以及,它究竟能给我们带来什么?
- 华为WeAutomate RPA产品首席规划师周为:企业数智化转型之路,RPA共创新价值
- 杨建荣的学习笔记排行榜(r2笔记100天)
- 迈阿密大学的计算机系咋样,迈阿密大学计算机科学专业
- python lambda 判断_Python lambda
- 【MPI编程】矩阵向量乘法--解法三(子矩阵块分解)【高性能计算】
- GitHub计算机书籍资源库,值得收藏
热门文章
- Java后端:html转pdf实战笔记
- 云原生时代下,微服务体系与 Serverless 架构的发展、治理与融合
- Python读写文件的七种模式(r,w,x,a,b,t,+)
- mysql初始设置_三 mysql 初始配置
- (LaTeX) Solved: 引用网页时出现的空格间距过大;网页链接的字体不符合要求
- 易语言-API 取窗口或者组件句柄的 屏幕坐标并限制区域 GetWindowRect ClipCursor getwindowrect GetClientRect WindowFromPoint
- NR数据库的物种注释
- linux 12541无监听程序,ORA-12541:TNS:无监听程序问题 解决办法
- 用Lombok项目减少样板代码(翻译自官方文档)
- 同步、异步、单工、双工、半双工有啥不同