token认证的设计
本文目录如下
请求Token
生成Token
使用Token
验证Token
扩展阅读
请求Token
在请求Token的API中,有以下参数
Query Parameters
service:(neccessary)授权服务的标识,表示要向谁请求tokenscope:(neccessary)client-id:(optinal)请求token的客户端id,比如docker-daemon发起的请求会将该字段设置为docker,harbor的复制策略中会将该字段设置为harbor-registry-client
Header Parameters
Authorization:(optional)携带的用户信息
Response Body
响应body为一个json,有三个字段
token:(neccessary)授权服务器返回的带有授权信息的tokenissued_at:(optional)token的签发时间,UTC标准时间格式expires_in:(optional)token在多少秒以后过期,如果没有说明则默认为60秒
示例
我们可以把上面的token拷贝到网页jwt.io中,查看token的明文形式。
在上面获取token的请求中,没有携带任何的用户信息。不过我们可以使用添加用户信息(用户名与密码)去获取token,如下:
其中YWRtaW46SGFyYm9yMTIzNDU=是admin:Harbor12345的base64编码
生成Token
token由三部分内容组成:Header、Payload和Signature。token的形式如下:
Header
Header有三个字段
typ:固定为JWTalg:签名算法,常用的有HS256、RS256等kid:key-id,签名算法中所使用的密钥的ID值
kid的生成有以下三个步骤
1、从签名算法使用的密钥中得到DER编码格式的公钥(public key) 2、对DER格式的公钥做sha256哈希,取前240bit 3、将这240bit使用base32编码,然后四个一组使用冒号:分隔
如下是Header的一个例子
生成kid的详细例子见本文末尾的扩展阅读
Payload
payload中的字段有
iss:(Issuer),token的签发者sub:(Subject),正在进行认证的用户的名字,如果是匿名用户则为空aud:(Audience),token的观众,即需要对token进行验证的服务的名字exp:(Expiration),过期时间,在这之后token应该看作是无效的;时间戳格式nbf:(Not Before),token有效的超始时间,在这之前token应当看作是无效的;时间戳格式iat:(Issued At),签发时间;时间戳格式jti:(JWT ID),token的id,(尚不清楚如何生成)access:权限集,下面还有三个字段typenameactions
payload的样例如下:
Signature
Header
对header内容去掉空白字符后得到
然后对该字符串进行base64Url编码(base64在线编码网址),得到token-header
base64Url就是先进行base64编码,再把得到的字符串中的+变成-,/变成_,去掉=
Payload
payload内容去掉空白字符后得到
然后对该字符串进行base64Url编码,得到token-payload
signature
token-signature的计算方法如下,先对token-header + "." + token-payload做sha256哈希(RS256就是RSA+SHA256),然后再使用RSA的私钥进行签名(sign),最后用base64Url进行编码,得到signature-token
由前面的token-header与token-payload得到的token-signature如下(RSA密钥见扩展阅读)
最后,对token-header、token-payload和token-signature进行组装,得到最终的token
使用Token
在得到token后,我们就可以在API请求的Header中添加token信息,比如下载镜像的manifest
验证Token
当Registry接收到一个携带token的API请求时,Registry需要从以下几个方面来验证Token
token的签发者(payload中的
iss)是可信的,即和registry的配置参数issuer一致确保registry是该token的观众,即payload中的
aud与registry的配置参数token-service一致检查payload中的
nbf与exp确保token在有效期内检查payload的access字段,确保该token能够访问该API
检查token的签名
扩展阅读
本文中使用到的RSA的私钥为(private_key.pem)
kid的生成
首先从RSA私钥中提取公钥,保存到文件public_key.pem中
然后将公钥文件由pem格式生成der格式
然后对der格式的公钥文件做sha256哈希
去掉十六进制的哈希值后四位得到
然后用base32(RFC4648)进行编码(base32在线编码网址),编码后得到
每四位一组,中间用:隔开,得到kid的值
Last updated
Was this helpful?