已发表的技术专栏(订阅即可观看所有专栏)
0 grpc-go、protobuf、multus-cni 技术专栏 总入口
4 grpc、oauth2、openssl、双向认证、单向认证等专栏文章目录
注意:
实话实说,
oauth2我并没有研究的十分透彻,还有很多地方不理解,如果有机会接触到真实的案例的话,再更新本篇文章。
本篇文章将自己的认识进行了总结,肯定有说的不对的地方,还请谅解。
如果有什么问题,可以留言,共同学习。
1、介绍 |
1.1、一般的认证与授权方案有哪些? |
- OAuth、
- 分布式 Session、
- OpenID
- JWT 等.
目前常用的是OAuth2
1.2、oauth2介绍 |
OAuth(开放授权)是一个开放标准,
允许用户让第三方应用访问该用户在某网站上存储的资源(如邮箱、手机、头像等),
而无需将用户名和密码提供给第三方应用。
1.3、oauth2使用场景? |
其重点在于为Web应用程序、桌面应用程序、移动设备以及室内设备的授权流程提供简单的客户端开发方式。
它为第三方应用提供对HTTP服务的有限访问,
既可以是资源拥有者通过授权允许第三方应用获取HTTP服务,也可以是第三方以自己的名义获取访问权限
2、OAuth2.0规定了四种授权方式 |
2.1、授权码(authorization_code)(最常用) |
- 用户登录授权
- 认证服务器创建授权码code、并将授权码重定向给客户端
- 授权码,是有用户ID,客户端ID组成
- base64编码
- 客户端携带授权码code,再次重定向到认证服务器,获取token
- token,是由用户ID,客户端ID(即CSDN,简书的ID)
- oauth2官方提供了base64、jwt方式创建token
- 认证服务器创建完token,反馈给客户端一侧
客户端一侧,获取到token, 就可以向微信一侧发起资源请求了。(这个过程,本次测试没有涉及到)
2.2、隐藏式(implicit) |
用户登录授权,用户直接拿token
常用于没有后端服务,只有前端的服务
2.3、密码方式(password) |
认证服务器端会验证用户的用户名和密码,通过后,认证服务器会创建token,将token返回给客户端
客户端携带token,就可以向资源方发起请求,获取指定用户的相关数据了。
2.4、客户端凭证(client_credentials) |
认证服务器端会验证客户端ID,通过后,认证服务器会创建token,将token返回给客户端
客户端携带token,就可以向资源方发起请求,获取指定用户的相关数据了。
2.5、换一个角度理解这4种方式 |
这4类方式,可以换一个角度理解:
如果想让认证服务器创建token的话,需要做一些身份校验工作,
不能随便调用我的接口,我就屁颠屁颠的去创建token吧。
那么,认证服务器说,我可以接收4种方式的身份校验工作
- 授权码方式
- 密码方式
- 客户端凭证方式
- 隐秘式方式
无论是授权码模式校验,密码式校验,还是客户端凭证式校验,都是想确定用户ID,获取用户ID,即确定用户身份的信息。
将用户信息封装到token里,这样资源方解析token,获取用户身份信息,才能将指定的用户信息数据反馈给客户端。
3、在认证和授权的过程中涉及到4种角色 |
- 资源拥有方(用户user、 resource owner)
- 比方说,用户对微信里的用户名,用户密码,用户头像,用户昵称等资源具有所有权
- 资源方(resource server):
- 例如微信,微信是负责对资源进行维护的,如对用户名,用户头像等资源进行维护
- 资源请求方(客户端、client):
- 例如简书调用微信登录,简书就是请求方;
- 或者,登录CSDN时,可以使用第三方账号(如,微信账号、微博账号)进行登录,此时CSDN需要有权限获取微信里用户的信息,此时CSDN属于资源请求方,也叫客户端
- 授权方(authorization server):
- oauth2,是一个独立的平台。
- 需要实现的服务
4、前提要求 |
- 在认证服务器一侧,
- 需要注册客户端ID,客户端密钥;
- 客户端每次向认证服务器发起token请求时,认证服务器都会进行客户端ID,密钥的校验
- 如果是客户端凭证式,认证服务器可以自定义客户端凭证校验处理函数(srv.SetClientAuthorizedHandler),来对客户端ID,授权码字段grant_type进行校验
- 可能需要注册用户的用户名和密码
- 如果授权方式是密码式的话,认证服务器就需要知道用户的用户名和密码
- 当认证服务器接收到客户端创建token请求后,就会对传过来的用户名和密码进行校验
- 因此,认证服务器需要提前通过某种方式获取到用户的用户名和密码
- 认证服务器,自定义密码校验处理器srv.SetPasswordAuthorizationHandler
- 需要注册客户端ID,客户端密钥;
- 在资源方一侧(如,微信一侧),
- 必须有用户ID,客户端ID;
- 即CSDN,或者简书必须提前向微信进行注册自己的ID号;
- 这样,当客户端一侧携带token数据,向微信一侧请求某个用户的资源数据时,
- 微信一侧接收到请求后,会解析token,获取用户ID,以及客户端ID,只有这两个满足后,才能将用户的数据反馈给客户端。
- 必须有用户ID,客户端ID;
其实,
- 客户端(如,CSDN, 简书之类的)
- 需要提前向认证服务器进行注册
- 需要提前向资源方进行注册
- 用户
- 肯定已经在资源方注册了。
- 如果是密码式的话,用户也需要提前向认证服务器进行注册
5、授权整体流程(此图很重要,一定要搞清楚,哪些代码是自己负责写的,哪些是人家的;自己是哪个角色要搞清楚) |
该图从官网截的
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
假设现在有4种角色:用户,CSDN,授权服务,微信;它们之间的关系:
在这个图里,要实现的是认证服务,你想想CSDN,微信,肯定不是你实现的吧。
图中所描述的流程应该是授权码方式
6、测试用例说明 |
本次测试直接使用go-oauth2官方提供的测试用例
7、在go-oauth2源码中授权码字段grant_type的有效值? |
grant_type值决定了oauth2认证的方式
在oauth2/const.go文件下
grant_type的有效值如下:
- authorizaiton_code,表示设置的是,通过授权码方式来获取token
- password,表示设置的是,通过密码式来获取token
- client_credentials,设置的是,通过客户端凭证式获取token
- __implicit
- refresh_token
其实,
还有一个值为code
表示设置的是 授权码;
认证服务器端检测到后,若为code,需要创建授权码,反馈给客户端
客户端有了授权码就可以再次向认证服务器获取token
8、参考 |
- oauth2API介绍
- oauth2官方测试用例
- 基于go-oauth2/oauth2实现OAuth 2.0 授权码方式
- 基于go-oauth2的sso服务
- 如何用GO实现OAuth2授权功能
- GO之认证与授权
下一篇文章
oauth2认证方式之授权码模式介绍