Loading

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';
                    }
                });

posted @ 2022-09-14 11:30  minqiliang  阅读(89)  评论(0编辑  收藏  举报
-->