@[TOC](JSON Web Token令牌(JWT)的使用(一)JWT的原理、配置、创建使用)
详情请查看jwt官网
jwt是通过客户端保存数据,而服务器根本不保存会话数据,每个请求都被发送回服务器。
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
典型的,一个JWT看起来如下图。
改对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。注意JWT对象为一个长字串,各字串之间也没有换行符,此处为了演示需要,我们特意分行并用不同颜色表示了。每一个子串表示了一个功能块,总共有以下三个部分:
JWT的三个部分如下。JWT头、有效载荷和签名,将它们写成一行如下。
因此,一个典型的JWT看起来是这个样子的:
xxxxx.yyyyy.zzzzz
接下来,具体看一下每一部分:
header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,用Base64对这个JSON编码就得到JWT的第一部分
JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。
Registered claims : 这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
Public claims : 可以随意定义。
Private claims : 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。
下面是一个例子:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
对payload进行Base64编码就得到JWT的第二部分
注意,不要在JWT的payload或header中放置敏感信息,除非它们是加密的。
为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥,签名算法是header中指定的那个,然对它们签名即可。
例如:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。
需要先进行配置,具体可以看:https://github.com/GetBlimp/django-rest-framework-jwt/blob/master/docs/index.md
下面是实例,在创建完用户之后创建jwt令牌并发送给前端
import datetime
REST_FRAMEWORK = {
# 异常处理指定
'EXCEPTION_HANDLER': 'shanghuishop.utils.exceptions.code_exp_handler',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication', # session认证
'rest_framework.authentication.BasicAuthentication' # 基本认证
)
}
# 设置过期时间
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=60*60*24),
}
要先写一个token然后加进fields里面:
token = serializers.CharField(label='JWT令牌-TOKEN', read_only=True)
内容是写在系列化器的create方法里,已经生成了user的
from rest_framework_jwt.settings import api_settings
def create(self, validated_data):
# 把不需要存进去的删掉
del validated_data['password_confirm']
del validated_data['phone_msg']
# 第一种方式进行加密
# user = super().create(validated_data)
# user.set_password(validated_data['password'])
# user.save()
# 第二种方式:用drf自带的用户方法来注册用户密码会进行加密
user = Users.objects.create_user(**validated_data)
# 手动创建用户令牌
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@2')
print(payload)
token = jwt_encode_handler(payload)
print(token)
# 给user动态添加属性
user.token = token
return user
返回的值是object类型
success: function (rec_data) {
console.log(rec_data);
var token = rec_data['token'];
console.log(token);
// 浏览器关闭则无效
// sessionStorage.token = token;
// 长期有效, 一般用这个,先做清除操作,避免之前遗留问题
localStorage.clear();
localStorage.token = token;
// 获取token
alert(localStorage.token)
}
获取完之后需要保存,两种做法:一个是sessionStrorage,一个是loaclStrorage一般用后一个