立即注册
10 登录注册之多方式登录
10 登录注册之多方式登录
一、后端
1、插件
>: pip install djangorestframework-jwt
2、多方式登录第一种方式
2.1、user/urls.py
from rest_framework.routers import SimpleRouter
from . import views
router = SimpleRouter()
router.register('', views.LoginViewSet, 'login')
urlpatterns = [
]
urlpatterns += router.urls
2.2、dev.py
import datetime
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
2.3、views.py
from django.shortcuts import render
from rest_framework.viewsets import ViewSet
from . import serializers, models
from luffyapi.utils.response import APIResponse
from rest_framework.decorators import action
class LoginViewSet(ViewSet):
# 局部禁用认证、权限组件
authentication_classes = ()
permission_classes = ()
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
serializer = serializers.LoginSerializer(data=request.data, context={'request': request})
if serializer.is_valid():
token = serializer.context.get('token')
# 原来要一个个拿信息
# username = serializer.context.get('username')
# icon = serializer.context.get('icon')
# 拿到登录用户,直接走序列化过程,将要返回给前台的数据直接序列化好给前台
user = serializer.context.get('user')
result = serializers.LoginSerializer(user, context={'request': request}).data
result['token'] = token # id,username,icon,token
return APIResponse(result=result)
return APIResponse(1, serializer.errors)
2.4、serializers.py
from rest_framework import serializers
from rest_framework import exceptions
from django.conf import settings
from . import models
class LoginSerializer(serializers.ModelSerializer):
# 覆盖,避免login校验username有数据库唯一字段约束的限制
username = serializers.CharField()
class Meta:
model = models.User
# username、password可以通过局部钩子指定详细的校验规则
fields = ('id', 'username', 'password', 'icon')
extra_kwargs = {
'id': {
'read_only': True,
},
'icon': {
'read_only': True,
},
'password': {
'write_only': True,
}
}
def validate(self, attrs):
# 多方式得到user
user = self._get_user(attrs)
# user签发token
token = self._get_token(user)
# token用context属性携带给视图类
self.context['token'] = token
''' 自己将user的信息逐个处理,传给视图
# 前台可能不仅仅只需要登录成功的token,可能还需要用户名、用户头像等
self.context['username'] = user.username
# 通过请求头格式化icon
request = self.context['request']
icon = 'http://%s%s%s' % (request.META['HTTP_HOST'], settings.MEDIA_URL, user.icon)
self.context['icon'] = icon
'''
# 将登录用户对象直接传给视图
self.context['user'] = user
return attrs
def _get_user(self, attrs):
import re
username = attrs.get('username')
if re.match(r'^1[3-9][0-9]{9}$', username):
user = models.User.objects.filter(mobile=username).first()
else:
user = models.User.objects.filter(username=username).first()
if not user:
raise exceptions.ValidationError({'username': 'username error'})
password = attrs.get('password')
if not user.check_password(password):
raise exceptions.ValidationError({'password': 'password error'})
return user
def _get_token(self, user):
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
payload = jwt_payload_handler(user) # 通过user对象获得payload
token = jwt_encode_handler(payload) # 通过payload对象获得token
return token
3、多方式登录第二种方式
3.1、user/urls.py
from django.urls import path
from . import views
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('', views.UserView, 'user')
router.register('', views.LoginView, 'login')
urlpatterns = [
]
urlpatterns += router.urls
3.2、user/views.py
# 多方式登录接口
class LoginView(GenericViewSet):
serializer_class = LoginSerializer
@action(methods=['POST'], detail=False)
def mul_login(self, request, *args, **kwargs):
try:
# 校验规则和签发token都写到序列化类中
ser = self.get_serializer(data=request.data, context={'request': request})
# context是视图类和序列化类中的桥梁,可以通过context互相传值,因为序列化类用到request,所以传值
ser.is_valid(raise_exception=True)
token = ser.context.get('token')
username = ser.context.get('username')
icon = ser.context.get('icon')
except Exception as e:
raise APIException(str(e))
return APIResponse(token=token, username=username, icon=icon)
3.3、user/serializers.py
from rest_framework import serializers
from .models import User
import re
from rest_framework.exceptions import ValidationError
class LoginSerializer(serializers.ModelSerializer):
# 因为username自己会有唯一键,所以要重写username字段
username = serializers.CharField()
class Meta:
model = User
fields = ['id', 'username', 'password', 'icon']
extra_kwargs = {
'id': {'read_only': True},
'username': {'read_only': True},
'password': {'write_only': True},
'icon': {'read_only': True}
}
def validate(self, attrs):
# 1.获取登录用户和密码
user = self._get_user(attrs)
# 2.签发token
token = self._get_token(user)
# 3.把token放入当前对象给视图类用
self.context['token'] = token
self.context['username'] = user.username
# 这个地址是服务端地址,服务端地址从request对象中可以取出request.META['HTTP_HOST']
request = self.context.get('request')
self.context['icon'] = 'http://%s/media/'%request.META['HTTP_HOST']+str(user.icon)
return attrs
def _get_user(self, attrs):
username = attrs.get('username')
password = attrs.get('password')
if re.match(r'^1[3-9][0-9]{9}$', username):
user = User.objects.filter(telephone=username).first()
elif re.match(r'^.+@.+$', username):
user = User.objects.filter(email=username).first()
else:
user = User.objects.filter(username=username).first()
if user and user.check_password(password): # 使用check_password检验加密秘密
return user
else:
raise ValidationError('用户名或密码错误')
def _get_token(self, user):
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
payload = jwt_payload_handler(user) # 通过user对象获得payload
token = jwt_encode_handler(payload) # 通过payload对象获得token
return token
二、前端
安装:前端项目目录下的终端
cnpm install vue-cookies
配置:main.js
import cookies from 'vue-cookies'
Vue.prototype.$cookies = cookies;
1、Login.vue
登录
{{ sms_interval }}
登录
2、Header.vue
登录
{{ sms_interval }}
登录
立即注册
3、Register.vue
{{ sms_interval }}
注册
立即登录