JWT的初步使用之重写自带的用户认证

官方文档:https://yiyibooks.cn/xx/Django_1.11.6/topics/auth/index.html

jwt 的初步应用流程:

  1. 用户登录或者注册账号,携带用户名和密码,传到服务器。
  2. 服务器利用前端传送来的信息,生成 jwt 命令。
  3. 服务器将jwt返回给前端浏览器。
  4. 如果用户进行访问,将携带jwt去访问后端服务器。
  5. 服务器将接收到的jwt令牌进行校验,如果校验通过,就可以返回用户信息等。
  6. 前端接收到后端发来的数据,然后在页面显示出来。

为何要自己重写认证登录

Django提供的内置的用户认证功能,只能单一的验证一种用户名,而现在有些网址可以支持多种用户名登录,如邮箱、手机号码,此时,我们就需要使用重写认证登录。

在utils文件夹里创建一个utils.py文件,然后编写内容为:

# 当前文件夹里面,定义的是自定义的认证系统
import re
from users import models
from django.contrib.auth.backends import ModelBackend

# 自定义认证方法
class UserPhoneEmailAuthBackend(ModelBackend):
    ''' 当前的类,是用来定义自定义的认证方法'''
    def authenticate(self, request, username=None, password=None, **kwargs):
        '''
        重写父类的方法
        :param request:
        :param username: 用户名、手机号码、邮箱
        :param password:
        :param kwargs:
        :return:
        '''
        # todo 不管是用户或者邮箱或者手机号码,第一件事情,是获取对象
        try:
            # todo 先通过正则,判断出手机号码
            if re.match(r'^1[3456789]\d{9}$', username):
                user = models.User.objects.get(phone=username)
            # todo 邮箱
            elif re.match(r'^[\w]+@[\w]+\.com$', username):
                user = models.User.objects.get(email=username)
            # todo 用户名
            else:
                user = models.User.objects.get(username=username)
        except models.User.DoesNotExist:
            user = None

        # todo 拿到user之后 进行校验
        if user is not None and user.check_password(password):
            return user

在settings配置文件里添加:

#配置自定义的认证
AUTHENTICATION_BACKENDS = [
    # 默认值:['django.contrib.auth.backends.ModelBackend']
    'shanghuiproject.utils.utils.UserPhoneEmailAuthBackend',
]

jwt自带的验证视图

直接在对应的urls.py文件里配置:

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    url(r'^login/$',obtain_jwt_token),  # 登录验证
]

重写jwt的返回内容

因为默认返回的内容只有token,有时我们需要得到更多的信息,如用户名,id等。

还是在utils文件夹里的utils.py文件里编写内容

# 认证成功后,返回给前端的自定义数据处理方法
def jwt_response_username_userid_token(token,user=None,request=None):
    '''
    JWT登录成功之后,自定义的返回数据的处理,
    :param token:
    :param user:
    :param request:
    :return:
    '''
    data = {
        'token': token,
        'username': user.username,
        'user_id': user.id,
    }
    return data

然后在settings.py文件下添加上面内容的路径:

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=200),  # 过期时间
    # 配置自定义的jwt返回内容路径
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'shanghuiproject.utils.utils.jwt_response_username_userid_token',
}

前端的登录按钮触发的ajax请求

前端点击按钮就会把用户名和密码通过ajax发送给后端,后端接收到数据,验证成功后会返回一个token,然后前端通过success回调函数将数据token进行保存。

$('#usersubmit').click(function () {
        var usernmae = $('#userloginname').val();
        var userpwd = $('#loginpwd').val();

        var data = {
            'username': usernmae,
            'password': userpwd,
        };

        data = JSON.stringify(data);

        $.ajax({
            url: 'http://127.0.0.1:8000/users/login/',
            method: 'POST',
            contentType: 'application/json',
            data: data,

            success:function (data) {
                console.log(data);
                token = data['token'];
                localStorage.clear();
                // sessionStorage.token = token; //浏览器关闭就失效
                localStorage.token = token; //长期有效
                console.log('从本地获取的token',localStorage.token);
                location.href = 'http://127.0.0.1:8080/templates/userinfo.html'
            },
            error: function (data) {
                console.log(data);
            }
        })
    })

前端返回结果:
在这里插入图片描述

JWT 如何返回用户信息

在serilizers.py文件下写一个序列器:

fields里面的元组只要填自己需要用到的字段就好

class LoginUserInfoSerilaizer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ('id','username','phone','email',)

在view.py文件编写视图类:

RetrieveAPIView视图里面自带put请求和get请求,get_object()返回的是单个模型。

class LoginUserInfoView(RetrieveAPIView):
    '''
    前端GET请求:将用户信息返回给前端
    '''
    # 1.需要指定序列化器
    serializer_class = serializers.LoginUserInfoSerilaizer
   
    # 2.指定单个模型
    def get_object(self):
        print(self.request.user)
        return self.request.user

urls.py 文件的内容:

urlpatterns = [
    url(r'^userinfo/$',views.LoginUserInfoView.as_view()),
]

前端通过get请求发送JWT值然后获取后端传送来的信息

最重要的是在前端的Ajax中需要添加下面代码:
注意:下面代码中JWT后面有一个空格

 headers:{
            'Authorization':'JWT ' + token 
        },

整个ajax请求代码:

    $.ajax({
        url: 'http://127.0.0.1:8000/users/userinfo/',
        method:'GET',
        headers:{
            'Authorization':'JWT ' + token 
        },
        success: function (data) {
            console.log(data);
            console.log('token',token);
            email = data['email'];
            phone = data['phone'];
            username = data['username'];
            console.log(email, phone, username);
            //在前端设置相对于的值
            $('.myusername').html(username).val(username);
            $('#myemail').val(email);
            $('#myphone').val(phone);
        },
        error: function (data) {
            console.log(data);
            console.log(data['status']);
            // 如果是401(JWT过期)错误,就跳转到登录界面
            if (data['status']==401){
                //location.href = 'http://127.0.0.1:8080/templates/login.html';
                location.href = '/templates/login.html?next=/userinfo.html'
            }
        }
    });

猜你喜欢

转载自blog.csdn.net/dakengbi/article/details/92799112