JWT的使用

登录验证

用户登录和鉴权的重要性不言而喻
由于HTTP请求无状态的特性,为了节省运算资源,有必要(?)提供一套登录机制,在验证通过后、一段时间内对需要登录的操作放行
常用的方法有:Session机制,JWT机制和OAuth机制 cookie-session

Session

Session,会话。在用户登录后,服务器存储用户会话的相关信息,并为客户端指定一个访问凭证,如果有客户端凭此凭证发出请求,则在服务端存储的信息中取出用户相关登录信息并使用
服务端返回的凭证常存储于Cookie中。此时Cookie与SessionStorage和LocalStorgae并无太多不同,是一种存储的载体,本质上来说,存在Cookie中的内容也可以存在别处

基于Session和其他服务器存储凭证的鉴权机制有一个问题,对分布式系统比较不友好
如果用户的请求会到达两台服务器上,那么如果其中一台没有登录过,鉴权就会失败
解决这个有数种方法:
一是存储的数据库是分布式的,访问任意一台机器时,实际上都会从分布式的数据库(数据中心)调取凭证
二是通过流量分发,保证同一SessionId的用户,每次请求都会到同一台服务器(数据库)上

JWT

JWT是一种无状态的鉴权机制。将用户登录后的一些信息(比如用户Id)和过期时间等信息存储在一个加密过的字符串中,当服务器收到请求的时候,进行解密并直接使用信息
JWT的组成:使用base64编码描述jwt的头部、使用base64编码的payload,以及加密签名
我们将使用jsonwebtoken模块管理JWT
缺点,服务器无法像session一样方便地管理用户登录状态

Cookie-Session

Express的一个中间件,与JWT类似,使用签名+明文的方法在cookie当中存储session,使用sha256算法进行加密

登录

明文存储用户密码是一件很不机智的事情,包括CSDN在内的一系列组织都出现过大量用户账号密码泄露的事故,如果明文存储密码,画美不看
我们使用Node.js自带的crypto模块中的pbkdf2算法,加密用户的密码,在登录时取出密码进行比对
使用时要注意:1.不能使用pbkdf2Sync方法;2.由于该算法耗时较长,要进行异步处理,可以学习utilities或者bluebird中的promisify方法

什么是JWT
JWT, 全称是JSON Web Token,
是一种易于使用、无状态的鉴权(Authorization)方式。
简单的来说,就是

Server端把JSON数据经过加密做成token,以授权给Client端。

当Client端登录完成以后,
Server端要返回一个7天有效的token,
那么对应的Python的样例代码会是这样的:
(使用了PyJWT包:pip install pyjwt)

import time

import jwt

exp = int(time.time()) + 86400 * 7  // 失效时间
user = 'liriansu'  // 用户表示
key = 'hunter2'  // 密钥
payload = {'exp': exp, 'user': user}  // JSON 数据
token = jwt.encode(payload, key)

print(token)
// token可能会长这样子
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.EoKoMCjq_zGqUg5HDfqw4EN7EiG6gMjkUZle0uGJDGU

关于hunter2也有个梗:弱密码hunter2

然后Client端每次在authorization header或者是query string里带上token。
Server端收到请求的时候,

用payload = jwt.decode(token, key)验证权限就行了。

验证通过以后,payload中就是整个JSON数据。
理论上你可以往token payload里塞任何_非敏感_数据。

所以综合来说,
假如使用JWT作为鉴权方式,
有以下几个特性:

Client端不用管任何加密/解密,只用存token,在请求里面带上就行了。
Server端可以实现不依赖外部存储鉴权,所有的数据都丢在token里。
也就是说鉴权这一步不需要File/MySQL/Redis之类的数据库,也能知道用户身份。
因为token带失效时间,所以需要在失效前/后再刷新token。

关于JWT的更多说明,实质上就是用个JSON数据当token,
这破token真的安全吗?能伪造吗?这个问题很尖锐,难以正面回答。

首先token/key泄漏了, 后果基本是跟其它鉴权方式一样严重。 其次JWT可以选择合适的加密方式, 加上合适的key是基本伪造不了的。
还有就是在JWT之外, 一定要用HTTPS! 不用JWT相当于没有门禁, 不用HTTPS基本是不穿内裤了。。。

简单的来说,JWT是由以下三部分组成的:

第一部分指定了加密算法(alg)和token类型(typ)。
第二部分就是我们定义的payload。
第三部分是由加密算法产生的签名。

我去,那token里的信息就是明文的啊?
是的。
所以token里不要带任何敏感信息。

文档上把payload里带的信息叫Claim,
有这么几个可选的Claim:

iss: Issuer, 签发方。
比如这个token是微信签发的,
那么可以是{'iss': 'wechat'}
aud: Audience, 接收方。
比如王者荣耀想用微信登录,
那么可以是{'aud': 'king-of-glory'}
exp: Expiration Time, 失效时间。
使用的是整形Unix时间戳,
关于时间戳可以看看《互联网上的日期和时间》
RFC7519里面还有一点很好玩,
就是上面每一个Claim最后都加了一句Use of this claim is OPTIONALRFC2119还定义过啥叫OPTIONAL

也就是说我们可以往payload里丢任何东西。
只要符合这种加密/解密/鉴权的方式,
我们都可以说“我们用了JWT”。

那token会不会很大?
有可能会。

所以payload里的东西能少则少,

还有就是传输JWT的时候,
相较于放query string里,
更推荐放在Request Headers里面。

下面就用个简单的表格来对比一下_我了解的_几种鉴权方式吧:

JWT, OAuth, Session, Hawk

在这里插入图片描述

JWT全称叫JSON Web Token,

小心别写了类似jwt_token这样的变量名了(语义重复)。
RFC7519还定义了JWT读起来是类似于jot的发音。
然而实际中交流都会说JWT(怕听不懂)。
JWT说是说用同一个key就行了,
不过我们在项目实际中还是根据不一样的user用了不一样的key。
(同时也用了数据库)
假如payload里带了失效时间,
理论上JWT签发后是不会失效的,
也就是Server端管理不了这些token。
(所以可以加个数据库来管)
用JWT想做“记住登录状态”这个功能的话,
可以设定token失效期比如是7天,
然后用户每天登录的时候刷一次token。
这样除非用户一周内都没登录,
才会请求重新登录。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Supernova_gu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值