Django REST framework JWT
Django REST framework JWT
我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT。
关于签发和核验JWT,我们可以使用Django REST framework JWT扩展来完成。
文档网站http://getblimp.github.io/django-rest-framework-jwt/
(1)安装配置
安装
pip install djangorestframework-jwt
配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
- JWT_EXPIRATION_DELTA 指明token的有效期
(2)使用
Django REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法
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的例子,需要在注册视图中创建token。
修改CreateUserSerializer序列化器,在create方法中增加手动创建token的方法
from rest_framework_jwt.settings import api_settings
class CreateUserSerializer(serializers.ModelSerializer):
"""
创建用户序列化器
"""
...
token = serializers.CharField(label='登录状态token', read_only=True) # 增加token字段
class Meta:
...
fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow', 'token') # 增加token
...
def create(self, validated_data):
"""
创建用户
"""
# 移除数据库模型类中不存在的属性
del validated_data['password2']
del validated_data['sms_code']
del validated_data['allow']
user = super().create(validated_data)
# 调用django的认证系统加密密码
user.set_password(validated_data['password'])
user.save()
# 补充生成记录登录状态的token
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)
user.token = token
return user
(3) 前端保存token
我们可以将JWT保存在cookie中,也可以保存在浏览器的本地存储里,我们保存在浏览器本地存储中
浏览器的本地存储提供了sessionStorage 和 localStorage 两种:
- sessionStorage 浏览器关闭即失效
- localStorage 长期有效
使用方法
sessionStorage.变量名 = 变量值 // 保存数据
sessionStorage.变量名 // 读取数据
sessionStorage.clear() // 清除所有sessionStorage保存的数据
localStorage.变量名 = 变量值 // 保存数据
localStorage.变量名 // 读取数据
localStorage.clear() // 清除所有localStorage保存的数据
如果前端使用的是vue就可以像下面这样保存token:
var vm = new Vue({
...
methods: {
...
on_submit: function(){
axios.post(...)
.then(response => {
// 记录用户的登录状态
sessionStorage.clear();
localStorage.clear();
localStorage.token = response.data.token;
localStorage.username = response.data.username;
localStorage.user_id = response.data.id;
location.href = '/index.html';
})
.catch(...)
}
}
})
如果某些功能页面需要用户登录,前端发请求的时候就可以像下面这样携带一个认证请求头:
axios.get(this.host + '/user/', {
// 向后端传递JWT token的方法
headers: {
'Authorization': 'JWT ' + this.token
},
responseType: 'json',
})
.then(response => {
// 加载用户数据,仅为示例
this.user_id = response.data.id;
this.username = response.data.username;
this.mobile = response.data.mobile;
this.email = response.data.email;
this.email_active = response.data.email_active;
})
.catch(error => {
if (error.response.status == 401 || error.response.status == 403) {
location.href = '/login.html?next=/user_center_info.html';
}
});