headers = {
'typ': 'JWT',
'alg': 'HS256'
}
# 构造payload
payload = {
'user_id': str(uuid.uuid4), # 自定义用户ID
'username': "wangbm", # 自定义用户名
'exp': datetime.datetime.utcnow + datetime.timedelta(minutes=5) # 超时时间,取现在时间,五分钟后token失效
}
token = jwt.encode(payload=payload, key=salt, algorithm="HS256", headers=headers).decode('utf-8')
# token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiODg4ZjIwZDktMDdlZC00MWJkLWIzMjktMTdjNmYwNThhMTRlIiwidXNlcm5hbWUiOiJ3YW5nYm0iLCJleHAiOjE1OTQ0MzQzMjZ9.kkEMhSx732lO6HWWNPNVQDHR9WuCEVxKgNol-LTbCP8
如果你只是测试使用,完全不用写那么多代码,用命令行即可
$ pyjwt --key="minggezuishuai" encode user_id=888f20d9-07ed-41bd-b329-17c6f058a14e username=wangbm exp=+120
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiODg4ZjIwZDktMDdlZC00MWJkLWIzMjktMTdjNmYwNThhMTRlIiwidXNlcm5hbWUiOiJ3YW5nYm0iLCJleHAiOjE1OTQ0MzQ4NTl9.A792th12kY1YnBWyVgbr5l6OQ5emRiETIjsnmIl4Ji8
文章插图
Base64URL 算法前面提到,Header 和 Payload 串型化的算法是 Base64URL 。这个算法跟 Base64 算法基本类似,但有一些小的不同 。
JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx) 。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_。这就是 Base64URL 算法 。
文章插图
JWT 如何保存?
关于浏览器应该将 JWT 保存在哪?这个问题,其实也困扰了我很久 。
如果使用搜索引擎去查,我相信你也一定会被他们绕晕 。
比如在这篇帖子(When and how to use it )里,作者的观点是,不应该保存在 localstorage 和 session storage,因为这样,第三方的脚本就能直接获取到 。
作者推荐的做法是,将 JWT 保存在 cookie 里,并设置 HttpOnly 。
文章插图
再比如这一篇帖子(JWT(JSON Web Token) : Implementation with Node)提到了要把 JWT 保存到 local-storage 。
文章插图
因此,我决定不再看网络上关于 『应将 JWT 保存的哪?』的文章 。而是自己思考,以下是我个人观点,不代表一定正确,仅供参考。
JWT 的保存位置,可以分为如下四种
- 保存在 localStorage
- 保存在 sessionStorage
- 保存在 cookie
- 保存在 cookie 并设置 HttpOnly
第三种,与第四种相比,区别在于 cookie 有没有标记 HttpOnly,没有标记 HttpOnly 的 cookie ,客户端可以将 JWT 通过 js 脚本放入 Header 里的 Authorization 字段 。这么看好像同时存在CSRF 攻击风险和 XSS 攻击风险,实则不然,我们虽然将 JWT 存储在 cookie 里,但是我们的服务端并没有利用 cookie 里的 JWT 直接去鉴权,而是通过 header 里的 Authorization 去鉴权,因此这种方法只有 XSS 攻击风险,而没有 CSRF 攻击风险 。
而第四种,加了 HttpOnly 标记,意味着这个 cookie 无法通过js脚本进行读取和修改,杜绝了 XSS 攻击的发生 。与此同时,网站自身的 js 脚本也无法利用 cookie 设置 header 的Authorization 字段,因此只能通过 cookie 里的 JWT 去鉴权,所以不可避免还是存在 CSRF 攻击风险 。
如此看来,好像不管哪一种都有弊端,没有一种完美的解决方案 。
文章插图
是的,事实也确实如此 。
所以我的观点是,开发人员应当根据实际情况来选择 JWT 的存储位置 。
- 当访问量/业务量不是很大时,可以使用 CSRF Token 来防止 CSRF 攻击
- 而如果访问量/业务量对服务器造成很大压力,或觉得服务器共享 token 对架构要求太高了,那就抛弃CSRF Token 的方式,而改用 JWT 。选择了 JWT ,就面临着要将 JWT 存储在哪的问题 。
- 若选择了 JWT ,那么请不要使用 cookie HttpCookie 来存储它,因为使用它还是会有 CSRF 攻击风险 。
- 那另外三种如何选择呢?这三种无论使用哪种,都不可避免有 XSS 攻击风险 。我的思路是,XSS 攻击通过其他的手段来规避,这里使用JWT 只有 防御 CSRF 攻击与服务器性能的优化,这两个目标 。
推荐阅读
- 火把节是哪个民族的?
- 黑洞会不会把地球吞了 黑洞如果吞噬地球会怎么样
- 巴西整容很厉害吗 巴西整容狂魔
- 为什么动物都愿意和大象玩 大象与什么动物生活在一起
- 化妆|如果想要不化妆就很漂亮,那就一定把自己已拥有的容貌保持好
- 黑洞能把地球吞噬吗 黑洞的吞噬范围
- 和田玉籽料|旧藏·和田玉籽料太平有象把件
- 【钦春语录】张冉:把自己变成了村里人
- 终于有人把常用的三种通讯方式:RS485、RS232、RS422讲明白了
- excel批量拆分工作簿,用VBA一键拆分,把数据分解到N个工作簿