Django中的JWT
一、什么是JWT(Json Web Token)
顾名思义,JWT就是Json Web Token,是在web应用中基于json的一种身份验证机制。
本质上就是把用户的信息通过base64编码后,加上一个头和一个签名,然后当作身份令牌发放给用户,使其能够通过这个token进行身份验证。
二、与session对比的优缺点
2.1 优点
1、session的用户信息全都是存在服务器上的,如果用户过多,会导致内存上的问题,而token不会
2、token扩展性好,session只能存储服务器上已有的结构性数据,而token是json,所以存啥都行
3、token可以在一定程度上防止csrf(原理是同源页面每次发请求都在请求头或者参数中加入Cookie中读取的Token来完成验证。CSRF只能通过浏览器自己带上Cookie,不能操作Cookie来获取到Token并加到http请求的参数中)
4、JWT可以跨语言支持,反正传的都是json,通用性很强
2.2 缺点
1、东西存太多了的话,会越来越大,每此访问都带着token,甚至可能让请求变成大头娃娃~(请求头比请求体大很多)
2、由于JWT只要签名合法,就是合法的,所以无法从自身层面上废除token,需要增加额外的逻辑来实现注销的功能
3、每次都要进行验证运算,消耗运算资源较大
三、JWT的构成
JWT分为三部分头部(header)、有效载荷(payload)、签名(signature)
3.1 头部
没啥好说的,就是告诉别人这是JWT,加密方式是xxx,一般长这样:
{
'typ': 'JWT',
'alg': 'HS256'
}
3.2 有效载荷(其实就是放内容的)
一般包含三个部分(其实就用公共的声明就行,省事):公共的声明、私有的声明、标准中注册的声明。
常用的 标准中注册的声明如下表:
名称 | 用途 |
---|---|
iss | jwt签发者 |
sub | jwt所面向的用户 |
aud | 接收jwt的一方 |
exp | jwt的过期时间,这个过期时间必须要大于签发时间 |
nbf | 定义在什么时间之前,该jwt都是不可用的 |
iat | jwt的签发时间 |
jti | jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击 |
nbf | 定义在什么时间之前,该jwt都是不可用的 |
3.3 签名
这里有一个很重要的东西——secret,一般保存在服务器端的配置文件里。
secret其实就是加密算法中的solt,有了这个才能加密和验证。
之所以token不会被别人伪造,是因为secret,所以如果secret泄露了,就完犊子了。因此,要保护好自己的secret哦。
3.4 样例
一个token大概长这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IumalOWjgeiAgeeOiyIsImlhdCI6MTUxNjIzOTAyMn0.huj1R4oYsSxbIpecRwGcDBzqFkL9dXA88P2ouM5xhT8
明显可以看出来,是由两个"."分成了三部分,分别是我们在上面说的,头部、有效负荷和签名,分别用base64都能给解出来。
四、django中的应用
4.1 后端安装与配置
安装:pip install djangorestframework-jwt
配置文件:
SECRET_KEY = 'lalala'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication'
]
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # token的有效时间
}
得到token之后,自己再封装成接口就OK了,生成token写法:
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
如果有不需要token认证的接口,可以这样写:
class WithoutTokenView(APIView):
# 免token认证,也可以在列表中加上自定义的认证类,实现authenticate方法即可
authentication_classes = []
4.2 前端写法
在登录之后,把token存在localstorage里,然后在请求头里加上一段Authorization:token即可。
以下写一段JQuery样例:
$.ajax({
url: "这里是一个url",
headers: {
"Authorization": "Bearer " + token
}
})
照着这种格式写就行了