drf-rest_framework-jwt相关

1.安装

pip install djangorestframework-jwt

2.创建超级用户,一步一步往填写,账户,密码,确认密码,若是弱密码,会问你"密码很弱,希望继续使用吗?(Y/N)",肯定是输入 y继续

 

 

 

3.然后就可以利用后台进行普通,或者其他用户的创建等操作了

 

 

 4.配置路由 urls.py文件

from app_jwt import views
from django.urls import path, re_path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('login/', obtain_jwt_token),
]

这里我使用了路由分发

 

 

 

 进行 postman访问 成功

 

 

 若是使用自居 带的进行访问的话 要在头上 加点东西

发送访问请求(必须带jwt空格)

 

 

 

 配置文件 settings.py中书写自己写的 自动签发与过期时间等设置

import datetime

JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app_jwt.utils.my_jwt_response_payload_handler',  # 这里的是我自己的app的文件里自己书写的
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),  # 过期时间,手动配置
}
from app_jwt.utils import my_jwt_response_payload_handler # 用这句话的能保用 词不会错,因为在配置文件中不会补全.
明显 是 app_jwt项目 下面有个 utils.py文件中 有个 类或者 方法叫
 my_jwt_response_payload_handler  我这里是个方法

下面书写自定义的文件的代码
def my_jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 100,
        'msg': "ok",
        'data': {
            'token': token,
        }
    }
这里的代码 是 自己写返回些什么内容 ,若是使用自带的话就只会返回一个token

 

 若是想要全局认证的话 自己写一个认证 类 配置settings.py文件

REST_FRAMEWORK = {
    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'users.app_jwt.utils.MyJwt',
    ),
}

下面是我自己定义的认证类

from rest_framework_jwt.utils import jwt_decode_handler
from rest_framework_jwt.authentication import BaseAuthentication
import jwt
from rest_framework.exceptions import AuthenticationFailed
from api import models


class MyJwt(BaseAuthentication):
    def authenticate(self, request):
        jwt_value = request.META.get('HTTP_AUTHORIZATION')
        if jwt_value:
            try:
                payload = jwt_decode_handler(jwt_value)
            except jwt.ExpiredSignatureError:
                raise AuthenticationFailed('签名过期!')
            except jwt.InvalidTokenError:
                raise AuthenticationFailed('用户不合法!')
            except Exception as e:
                raise AuthenticationFailed(str(e))
            user = models.User.objects.get(pk=payload.get('user_id'), username=payload.get('username'))
            return user, jwt_value
        raise AuthenticationFailed('您未携带token认证信息!')
from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from app_jwt import serializer
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated

from .utils import MyJwt


class GoodsAPIView(APIView):
    authentication_classes = [] # 配置了全局的话,局部禁用加上这句就可以了
    authentication_classes = [MyJwt] # 未配置全局的话,局部使用 加上这句 后面是自己定义的认证类
    permission_classes = [IsAuthenticated] # 都要配合权限认证一块儿使用

    def get(self, request, *args, **kwargs):
        return Response('good信息!')

多方式登录,(用户名/手机号/邮箱)

视图文件 views.py

class LoginView(ViewSet):
    def login(self, request, *args, **kwargs):
        login_serializer = serializer.LoginModelSerializer(data=request.data)
        login_serializer.is_valid(raise_exception=True)
        token = login_serializer.context.get('token')
        return Response({'status': 200, 'msg': '登录成功!', 'token': token, })

序列化器 serializer.py

class LoginModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = models.User
        fields = ['username', 'password']

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        elif re.match('^.*@.*$', username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()

        if user:
            if user.check_password(password):
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)
                self.context['token'] = token

                return attrs
            else:
                raise ValidationError('密码错误!')
        else:
            raise ValidationError('账户不存在!')

路由文件 urls.py

from app_jwt import views
from django.urls import path, re_path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('login/', obtain_jwt_token),
    path('test/', views.TestAPIView.as_view()),
    path('goods/', views.GoodsAPIView.as_view()),
    #登录相关   
    path('login1/', views.LoginView.as_view({'post': 'login'})),
    path('login2/', views.Login2View.as_view({'post': 'login'})),



]

也可以把 序列化器中的相关逻辑语句写在视图文件中像这样:

class Login2View(ViewSet):
    def login(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        elif re.match('^.*@.*$', username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()
        if user:
            if user.check_password(password):
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)
                return Response({'status': 200, 'msg': '登录成功!', 'token': token, })
            raise ValidationError('密码错误 !')
        raise ValidationError('账户不存在!')

逻辑是从上往下走的,所以在还没有返回数据之前,写在哪里都是可以的.

 

posted @ 2020-07-15 21:33  学海无涯苦中作乐  阅读(172)  评论(0编辑  收藏  举报