Json web token
2021-02-02 05:13
标签:并且 cond jsm 类型 用户id 集群 targe tps get JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案 互联网服务离不开用户认证,一般流程是这样的 这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。 举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现? 一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。 另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。 在项目开发中,一般会按照上图所示过程进行认证; 即: 用户登录成功之后,服务器给浏览器返回一个token,以后用户再访问浏览器携带token再去服务端发送请求,服务端效验token的合法性,合法则给用户展示数据,否则,返回一些错误信息 深入了解jwt:https://www.freebuf.com/articles/web/180874.html 传统token方式和jwt在认证方面有什么差异 jwt的生成格式如下,由 生成规则如下 最后将三段字符串通过 注意: base64url加密是先做base64加密,然后将 基于python 的 pyjwt模块创建jwt的token 安装jwt 一般在认证成功之后,会把jwt生成的token返回给用户,以后用户再次访问的时候就要携带token,此时jwt需要对token进行超时和合法性校验 获取token后,会按照以下步骤进行校验 在用户登录成功以后,生成token并返回,用户再来访问时需携带token 此示例在django的中间件中对token进行效验,内部编写了两个中间件来支持用户通过两种方式传递token Json web token 标签:并且 cond jsm 类型 用户id 集群 targe tps get 原文地址:https://www.cnblogs.com/CatdeXin/p/13173495.html
跨域认证问题
1、用户向服务器发送用户名和密码。
2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
3、服务器向用户返回一个 session_id,写入用户的 Cookie。
4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。
JWT认证流程
用户登录成功以后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需要携带token,服务端接收到token之后,需要去数据库或缓存里取校验token是否超时,合法
用户登录成功以后,服务端通过jwt生成一个随机token给用户(服务器无需保留token),以后用户访问时需携带token,服务端接受到token之后,通过jwt对token进行校验是否超时,是否合法
JWT创建TOKEN
jwt的原理
.
连接的三段字符串组成eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva G4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
{
‘typ‘: ‘JWT‘,
‘alg‘: ‘HS256‘
}
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
....
}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
.
拼接起来,然后进行hs256加密,然后对hs256密文进行base64url加密,得到token第三段base64url(
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
your-256-bit-secret (秘钥加盐)
)
)
.
拼接起来,就成了jwt的token-
代替+
及_
代替/
代码实现
pip install pyjwt
import jwt
import datetime
SALT = "ASDASDADFVQWEQFq@eq!dfqwetwgsdfaCADVQEERQERWQEQ134145235!#$!#"
# 设置超时 时间
# timeout = datetime.datetime.now() + datetime.timedelta(seconds=70) # 本地时间
timeout = datetime.datetime.utcnow() + datetime.timedelta(seconds=70) # 世界时间
def create_jwt():
# 构造header
headers = {
‘typ‘: ‘jwt‘,
‘alg‘: ‘HS256‘
}
"""headers 中一些固定参数名称的意义"""
# jku: 发送JWK的地址;最好用HTTPS来传输
# jwk: 就是之前说的JWK
# kid: jwk的ID编号
# x5u: 指向一组X509公共证书的URL
# x5c: X509证书链
# x5t:X509证书的SHA-1指纹
# x5t#S256: X509证书的SHA-256指纹
# typ: 在原本未加密的JWT的基础上增加了 JOSE 和 JOSE+ JSON。JOSE序列化后文会说及。适用于JOSE标头的对象与此JWT混合的情况。
# crit: 字符串数组,包含声明的名称,用作实现定义的扩展,必须由 this->JWT的解析器处理。不常见。
# 构造payload
payload = {
‘user_id‘: 1, # 自定义用户id
‘username‘: ‘nayue‘, # 自定义用户名
‘exp‘: timeout # 超时时间
}
"""payload 中一些固定参数名称的意义, 同时可以在payload中自定义参数"""
# iss 【issuer】发布者的url地址
# sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段
# aud 【audience】接受者的url地址
# exp 【expiration】 该jwt销毁的时间;unix时间戳
# nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳
# iat 【issued at】 该jwt的发布时间;unix 时间戳
# jti 【JWT ID】 该jwt的唯一ID编号
result = jwt.encode(
headers=headers, # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
payload=payload, # payload, 有效载体
key=SALT, # 进行加密签名的密钥
lgorithm=‘HS256‘ # 指明签名算法方式, 默认也是HS256
).decode("utf-8") # python3 编码后得到 bytes, 再进行解码(指明解码的格式), 得到一个str
return result
if __name__ == "__main__":
token = create_jwt()
print(token)
# eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Im5heXVlIiwiZXhwIjoxNTkxMzYzMTkyfQ.ue2bHYw6f555OiiPAj_Rmd3hKlIQNtOtYJ3unPiB80g
JWT校验token
header_segment
,payload_segment
,crypto_segment
三部分header_segment
进行base64url解密,得到header
payload_segment
进行base64url解密,得到payload
crypto_segment
进行base64url解密,得到signature
signature
部分数据进行合法性校验
signing_input
HS256
siging_input
进行加密,将得到的结果和signature密文进行比较import jwt
from jwt import exceptions
def get_payload(jwt_token):
try:
# 需要解析的 jwt_token 密钥 使用和加密时相同的算法
data = jwt.decode(jwt_token, SALT, algorithms=‘HS256‘)
# 解析出来的就是 payload 内的数据
return data
# 如果 jwt 被篡改过; 或者算法不正确; 如果设置有效时间, 过了有效期; 或者密钥不相同; 都会抛出相应的异常
except exceptions.ExpiredSignatureError:
return "token失效"
except jwt.DecodeError:
return "token认证失败"
except jwt.InvalidTokenError:
return "非法的Tooken"
except Exception as error:
return error
if __name__ == "__main__":
# token = create_jwt()
token = "eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Im5heXVlIiwiZXhwIjoxNTkxMzM3NjA5fQ.5NHXMITig2reOFUngQg4aknHa3bT5wurVnci6NWvEQw"
data = get_payload(token)
print(data) # {‘user_id‘: 1, ‘username‘: ‘nayue‘, ‘exp‘: 1591363192}
JWT总结
注意
JSON WEB TOKEN 实战
Django案例
Django rest framework案例
flask案例
上一篇:C++ 动态类型识别