2020-11-21

drf——基于jwt的多方式登录以及自定义多方式登录

一、基于jwt的多方式登陆

1 手机号+密码 用户名+密码 邮箱+密码2 流程分析(post请求): -路由:自动生成(推荐自动生成,自己手写也行)  -视图类:ViewSet(ViewSetMixin, views.APIView) -序列化类:重写validate方法,在这里面对用户名和密码进行校验

代码实现

models.py----->进行数据迁移

from django.db import modelsfrom django.contrib.auth.models import AbstractUserclass UserInfo(AbstractUser): phone = models.CharField(max_length=32, unique=True)

settings.py

INSTALLED_APPS = [ ... 'rest_framework']#扩写AUTH_USER表AUTH_USER_MODEL = 'app01.UserInfo'

views.py

from rest_framework.viewsets import ViewSetfrom app01.serializer import LoginSerializerfrom app01.utils import APIResponseclass LoginViewSet(ViewSet): def create(self, request, *args, **kwargs):  # 实例化得到一个序列化类的对象  # ser=LoginSerializer(data=request.data,context={'request':request})  ser = LoginSerializer(data=request.data)  # 序列化类的对象的校验方法  ser.is_valid(raise_exception=True) # 字段自己的校验,局部钩子校验,全局钩子校验  # 如果通过,表示登录成功,返回手动签发的token  token = ser.context.get('token')  username = ser.context.get('username')  return APIResponse(token=token, username=username)  # 如果失败,不用管了

serializer.py

from rest_framework import serializersfrom app01.models import UserInfoimport refrom rest_framework.exceptions import ValidationErrorfrom rest_framework_jwt.utils import jwt_encode_handler, jwt_payload_handlerclass LoginSerializer(serializers.ModelSerializer): #重写username不然报错 username = serializers.CharField() class Meta:  model = UserInfo  fields = ['username', 'password'] def validate(self, attrs):  # username可能是邮箱,手机号,用户名  username = attrs.get('username')  password = attrs.get('password')  # 如果是手机号  if re.match('^1[3-9]\d{9}$', username):   # 以手机号登录   user = UserInfo.objects.filter(phone=username).first()  elif re.match('^.+@.+$', username):   # 以邮箱登录   user = UserInfo.objects.filter(email=username).first()  else:   # 以用户名登录   user = UserInfo.objects.filter(username=username).first()  # 如果user有值并且密码正确  if user and user.check_password(password):   # 登录成功,生成token   # drf-jwt中有通过user对象生成token的方法   payload = jwt_payload_handler(user)   token = jwt_encode_handler(payload)   # token是要在视图类中使用,现在我们在序列化类中   # self.context.get('request')   # 视图类和序列化类之间通过context这个字典来传递数据   self.context['token'] = token   self.context['username'] = user.username   #一定要记得return   return attrs  else:   raise ValidationError('用户名或密码错误')

utils.py

from rest_framework.response import Responseclass APIResponse(Response): def __init__(self, code=100, msg='成功', data=None, status=None,     headers=None, content_type=None, **kwargs):  dic = {'code': code, 'msg': msg}  if data:   dic['data'] = data  dic.update(kwargs)  super().__init__(data=dic, status=status, headers=headers, content_type=content_type)

urls.py

注意:自动生成路由,四种对应关系

 

 

from django.urls import pathfrom rest_framework.routers import SimpleRouterfrom app01 import viewsrouter = SimpleRouter()#必须要加,basename='login',不然会报错router.register('login', views.LoginViewSet,basename='login')print(router.urls)urlpatterns = [ ...
  #path('login/', views.LoginViewSet.as_view({'post':'create'})), 可以用这种自己手写的路由]urlpatterns += router.urls

登录方式: >二、自定义user表,签发token,认证类的代码实现多方式登录

models.py

from django.db import modelsclass MyUser(models.Model): username = models.CharField(max_length=32) #字段名一定要叫username不然要自己重写,具体看源码 password = models.CharField(max_length=32) phone = models.CharField(max_length=32) email = models.EmailField()

utils.py

from rest_framework.response import Responseclass APIResponse(Response): def __init__(self, code=100, msg='成功', data=None, status=None,     headers=None, content_type=None, **kwargs):  dic = {'code': code, 'msg': msg}  if data:   dic['data'] = data  dic.update(kwargs)  super().__init__(data=dic, status=status, headers=headers, content_type=content_type)

views.py

from rest_framework.views import APIViewfrom app01.utils import APIResponseimport refrom app01.models import MyUserfrom rest_framework_jwt.settings import api_settingsjwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLERjwt_encode_handler = api_settings.JWT_ENCODE_HANDLERfrom rest_framework_jwt.views import obtain_jwt_tokenclass MyLoginView(APIView): def post(self, request, *args, **kwargs):  username = request.data.get('username')  password = request.data.get('password')  # 如果是手机号  if re.match('^1[3-9]\d{9}$', username):   # 以手机号登录   user = MyUser.objects.filter(phone=username).first()  elif re.match('^.+@.+$', username):   # 以邮箱登录   user = MyUser.objects.filter(email=username).first()  else:   # 以用户名登录   user = MyUser.objects.filter(username=username).first()  # 如果user有值并且密码正确,注意这里user.password == password  if user and user.password == password:   # 登录成功,生成token   # drf-jwt中有通过user对象生成token的方法   payload = jwt_payload_handler(user)   token = jwt_encode_handler(payload)   return APIResponse(token=token, username=user.username)  else:   return APIResponse(code=101, msg='用户名或密码错误')

urls.py

from django.contrib import adminfrom django.urls import pathfrom app01 import viewsurlpatterns = [ path('login2/', views.MyLoginView.as_view()),]

在自定义登录的基础上,加上自定义的认证,来查询订单信息

auth.py

from rest_framework_jwt.utils import jwt_decode_handlerimport jwtfrom rest_framework.exceptions import AuthenticationFailedfrom rest_framework_jwt.authentication import BaseJSONWebTokenAuthenticationfrom app01.models import MyUserclass JwtAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request):  token=request.META.get('HTTP_Authorization'.upper())  try:   payload = jwt_decode_handler(token)  except jwt.ExpiredSignature:   raise AuthenticationFailed('过期了')  except jwt.DecodeError:   raise AuthenticationFailed('解码错误')  except jwt.InvalidTokenError:   raise AuthenticationFailed('不合法的token')  # 得到的user对象,应该是自己user表的user对象  print(payload)  # user=MyUser.objects.get(id=payload['user_id']) 这样写不好,会每次都查一次数据库  user=payload  return (user, token)

views.py 加上以下认证代码

from app01.auth import JwtAuthenticationclass OrderAPIView(APIView): authentication_classes = [JwtAuthentication, ] def get(self, request):  # print(request.user) # 自己的user对象  print(request.user) # user是个字典,内部有user_id,  # 后续要查询该用户的所有订单,直接根据user_id查询即可  return APIResponse(msg='查询订单成功')

urls.py

urlpatterns = [ path('order/', views.OrderAPIView.as_view()),]

 









原文转载:http://www.shaoqun.com/a/492753.html

粉丝通:https://www.ikjzd.com/w/743

e邮宝:https://www.ikjzd.com/w/594.html?source=tagwish

走秀网:https://www.ikjzd.com/w/2427


一、基于jwt的多方式登陆1手机号+密码用户名+密码邮箱+密码2流程分析(post请求):-路由:自动生成(推荐自动生成,自己手写也行)-视图类:ViewSet(ViewSetMixin,views.APIView)-序列化类:重写validate方法,在这里面对用户名和密码进行校验代码实现models.py----->进行数据迁移fromdjango.dbimportmodelsfromd
启明星软件:启明星软件
白色清关:白色清关
番禺哪里好玩?番禺有什么好玩的地方?:番禺哪里好玩?番禺有什么好玩的地方?
2020华侨城·自贡灯会暨深圳欢乐谷首届幻彩灯光节开始了?:2020华侨城·自贡灯会暨深圳欢乐谷首届幻彩灯光节开始了?
口述:认识两个月女友花了我1万块:口述:认识两个月女友花了我1万块

No comments:

Post a Comment