借鉴:https://www.bilibili.com/video/av328501573
1、oauth2流程简介
1、角色介绍
1、资源拥有方:用户user
2、资源方:例如微信
3、资源请求方:例如简书调用微信登录,简书就是请求方
4、授权方:oauth2,是一个独立的平台。我们要实现的地方
2、流程介绍
client:资源请求方,也就是简书
resource owner:资源拥有者,也就是用户
authorization server:oauth平台
resource server :也就是微信
3、授权流程(grant_type)
1、授权码(authorization_code)最常用:
用户登录授权,先拿code。
然后使用code换token
2、隐藏式(implicit):
用户登录授权,用户直接拿token
常用语没有后端,只有前端的服务
3、密码方式(password):
验证客户端,直接用用户名密码拿token
4、客户端凭证(client_credentials):
验证客户端,直接拿token
2、go-oauth2简介
文档:http://godoc.org/gopkg.in/oauth2.v3
项目地址:https://github.com/go-oauth2/oauth2
3、了解demo项目
项目链接:https://github.com/llaoj/oauth2
该项目主要实现了4种授权流程和sso的单点登录
1、授权码方式(authorization_code)
1、获取code
请求:get /authorize
请求参数:
1、client_id:需要客户端向oauth2 server注册的client_id,该项目中已经加了两个测试 test_client_1和test_client_2
2、response_type:授权类型,固定值是code,如果是其他授权流程就是别的
3、scope:权限范围,默认all
4、state:标志性字段,防止别人篡改。
5、redirect_uri:返回code的回调地址,返回时链接会拼接?code=返回的code&state=xyz
参数示例:
如果登录会直接跳转到redirect_uri,否则会去登录
http://localhost:9096/authorize?client_id=test_client_1&response_type=code&scope=all&state=xyz&redirect_uri=http://localhost:9093/cb
返回示例:http://localhost:9093/cb?code=PRRCYIZRNJWWQDI3S5UYLQ&state=xyz
2、根据code获取token
请求:post /token
Authorization:
basic auth
username:client_id
password:client_secret
请求头 header:
Content-Type:application/x-www-form-urlencoded
请求参数:
grant_type:固定值:authorization_code
code:返回的code
redirect_uri:回调地址,和获取code的回调一致
返回值:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyMjIyMjIiLCJleHAiOjE1ODU3MTU1NTksInN1YiI6InRlc3QifQ.ZMgIDQMW7FGxbF1V8zWOmEkmB7aLH1suGYjhDdrT7aCYMEudWUoiCkWHSvBmJahGm0RDXa3IyDoGFxeMfzlDNQ",
"expires_in": 7200,
"refresh_token": "JG7_WGLWXUOW2KV2VLJKSG",
"scope": "all",
"token_type": "Bearer"
}
3、刷新token
请求:post /token
Authorization:
basic auth
username:client_id
password:client_secret
请求头 header:
Content-Type:application/x-www-form-urlencoded
请求参数:
grant_type:固定值:refresh_token
refresh_token:之前返回的refresh_token
4、解析token
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyMjIyMjIiLCJleHAiOjE1ODU3MTU1NTksInN1YiI6InRlc3QifQ.ZMgIDQMW7FGxbF1V8zWOmEkmB7aLH1suGYjhDdrT7aCYMEudWUoiCkWHSvBmJahGm0RDXa3IyDoGFxeMfzlDNQ
token以点为分割
第一部分:eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9
算法以及基本信息
第二部分 (重要):eyJhdWQiOiIyMjIyMjIiLCJleHAiOjE1ODU3MTU1NTksInN1YiI6InRlc3QifQ
业务以及用户相关的信息,我们需要对其base64解码
解码结果为:{"aud":"test_client_1","exp":1624621539,"sub":"admin"}
aud:客户端id
exp:过期时间
sub:登录账号
第三部分:ZMgIDQMW7FGxbF1V8zWOmEkmB7aLH1suGYjhDdrT7aCYMEudWUoiCkWHSvBmJahGm0RDXa3IyDoGFxeMfzlDNQ
主要是签名之类的信息
2、隐式授权(implicit)
适用于没有后端的且对安全要求不高的应用,用户授权登录后,直接给发token。
为了安全,隐式授权的刷新token功能。每次需要重新获取token
请求:get /authorize
请求参数:
client_id :需要客户端向oauth2 server注册的client_id,该项目中已经加了两个测试 test_client_1和test_client_2
response_type:固定值token
score:权限,默认all
state:验证请求的字段
redirect_uri:回调
请求实例:
http://localhost:9096/authorize?client_id=test_client_1&response_type=token&scope=all&state=xyz&redirect_uri=http://localhost:9093/cb
返回示例:
http://localhost:9093/cb#access_token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X2NsaWVudF8xIiwiZXhwIjoxNjI0ODY0MzU4LCJzdWIiOiJhZG1pbiJ9.6q4C34PguLWJ2td-6OPNPwJPbE9HXsCKupi24I45MJT1blAjftWY0moNEnPxItxCb182Pf_HayZah0oACzGBhQ&expires_in=3600&scope=all&state=xyz&token_type=Bearer
3、密码方式(password)
直接使用账号密码申请令牌,无需打开页面
请求:post /token
Authorization:
basic auth
username:client_id
password:client_secret
请求头 header:
Content-Type:application/x-www-form-urlencoded
请求参数:
grant_type:固定值:password
username:用户名
password:密码
score:权限,默认all
返回示例:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X2NsaWVudF8xIiwiZXhwIjoxNjI0ODY4ODYzLCJzdWIiOiJhZG1pbiJ9.wpEP7rrhyaszx1zGo8RjCuO8NjES4cf0ON0EouQw9eXk6ihJ9wcpb4VdCPALrNY73KM6xpgdo9svOtlYxuQFLg",
"expires_in": 7200,
"refresh_token": "1T8ZJK_HXD6FCQUZQTNRWQ",
"token_type": "Bearer"
}
4、客户端凭证(client_credentials)
使用oauth2的client_id和client_secret直接获取到token
因为和用户没有关系,所以多个用户可以使用同一个token
请求:post /token
Authorization:
basic auth
username:client_id
password:client_secret
请求头 header:
Content-Type:application/x-www-form-urlencoded
请求参数:
grant_type:固定值:client_credentials
score:权限,默认all
返回示例:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0X2NsaWVudF8xIiwiZXhwIjoxNjI0ODcwMzI2fQ.2Z889rQlrljNiX1fPIlfcDf2Ji0Izh3MkYVJ357FKPBfbATIJh_FMtqRM-WhOnzsGRNagN22dRu82XUrAmk23A",
"expires_in": 7200,
"token_type": "Bearer"
}
5、验证token
资源端验证token,score和domain使用的
请求:get /test
Authorization:
bearer Token
Token:access_token
返回示例:
{
"client_id": "test_client_1",
"domain": "http://localhost:9093",
"expires_in": 3581,
"scope": "all",
"user_id": "admin"
}
6、退出登录
专门为sso开发,跳转到指定链接
请求:get /logout?redirect_uri=
请求参数:
redirect_uri:退出后跳转的页面,需要urlencode
请求示例:
下方的跳转链接使用的是授权码方式的获取code的链接
http://localhost:9096/logout?redirect_uri=http%3A%2F%2Flocalhost%3A9096%2Fauthorize%3Fclient_id%3Dtest_client_1%26response_type%3Dcode%26scope%3Dall%26state%3Dxyz%26redirect_uri%3Dhttp%3A%2F%2Flocalhost%3A9093%2Fcb