<登录功能 1 session>
==vue前端==
// 点击登录触发
Login() {
// 通过element自定义表单校验规则,校验用户输入的用户信息
this.$refs["ruleForm"].validate(valid => {
//如果通过校验开始登录
if (valid) {
// 发送ajax
this.$axios.post("/users/login/", {
user: this.LoginUser.name,
pwd: this.LoginUser.pass,
})
.then(res => {
console.log("@@登录的响应:", res)
// 200代表登录成功,其他的均为失败
if (res.data.code == 200) {
// res.data为后端响应的json
// 隐藏登录组件
this.isLogin = false;
// 登录信息存到本地缓存
let user = JSON.stringify(res.data.user);
//要求后台返回的数据
//{
// "code":200,
// 'msg': "欢迎user",
// "user":{
// userName:"xxx",
// },
//}
// 前端存储用户信息,表示登录成功
localStorage.setItem("user", user);
// sessionStorage.setItem("")
// 登录信息存到vuex,控制页面欢迎信息
this.setUser(res.data.user);
// 弹出通知框提示登录成功信息
this.notifySucceed(res.data.msg);
} else {//响应不是200
// 清空输入框的校验状态
this.$refs["ruleForm"].resetFields();
// 弹出通知框提示登录失败信息
this.notifyError(res.data.msg);
}
})
.catch(err => {
console.log(err)
return Promise.reject(err);
});
} else {//未通过用户校验
return false;
}
});
}
django/路由
# /users/login/
path("login/", Login.as_view()),
django/视图
from django.contrib.auth.hashers import check_password
from django.contrib.auth import authenticate
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *
class Login(APIView):
def post(self, request):
# 1. 获取前端数据
# 前端发送post 数据{user:xxx, pwd:xxx}
username = request.data.get("user")
password = request.data.get("pwd")
#2. 验证用户
# user = authenticate(username=username,password=password)
try:
user = User.objects.get(username=username)
except:
return Response({"code":204,"msg":"用户不存在!"})
# 用户存在,验证密码
if check_password(password, user.password):
#密码正确
#会话保持,django后端只需要简单设置session,返回的响应会带着sessionid---->Vue代理处理cookie存储
request.session["username"] = username
return Response({"code":200, "msg":"欢迎%s"%username, 'user':{"userName":username, 'uid':user.id}})
# 验证未通过
res = Response({"code":204, "msg":"用户名或密码不正确!"})
return res
<登录功能 2 >携带 jwt token
自定义登录视图,使用pyjwt
自己生成 token
, 此类方案支持所有的python
框架
pip install jwt
生成token
import datetime
import jwt #需要安装pip install pyjwt
from django.conf import settings
def generate_token(user):
"""
:param user: 用户对象
:return: 生成的token
"""
#自己组织payload
payload = {
'user_id': user.id,
'username': user.username,
'exp': datetime.datetime.now() + datetime.timedelta(seconds=300)
}
# token 要自己生成: 第二部分的载荷,盐部分, 算法
token = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm='HS256')
return token
jdango/登录视图
from django.contrib.auth import authenticate
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *
class Login(APIView):
def post(self, request):
#获取前端数据
username = request.data.get('user')
password = request.data.get('pwd')
user = authenticate(username=username, password=password)
if user:
token = generate_token(user)
return Response({
'code':200,
'msg': '登录成功!',
'token': token,
'user': {
'userName': user.username,
'uid': user.id
}
})
else:
return Response({"code":204, 'msg': '用户名或密码错误'})
django/路由
urlpatterns = [
path('login/', Login.as_view()),
]
Vue前端存储token
localStorage.setItem("token", res.data.token)
#后续的请求 携带token
let token = localStorage.getItem("token")
----------------------------------------------------------------------------------------------------------------------------
django方案二 携带token
自定义登录视图,使用 djangorestframework-jwt提供的 方法生成token
,此类方案只能支持django
框架
pip install djangorestframework-jwt
登录视图
from rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handler
from django.contrib.auth import authenticate
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *
class Login(APIView):
def post(self, request):
username = request.data.get('user')
password = request.data.get('pwd')
user = authenticate(username=username, password=password)
if user:
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
return Response({
"code":200,
'msg': '登录成功!',
'token': token,
'user': {
'userName': user.username,
'uid': user.id
}
})
else:
return Response({"code":200, 'msg': '用户名或密码错误!'})
路由配置
urlpatterns = [
path('login/', Login.as_view()),
]
---------------------------------------------------------------------------------------------------------------------------------
多方式登录
django内置的用户认证方式只支持 用户名和密码,而实际的项目开发中,登录方式往往不止一种
因此,需要重写用户认证类,指明新的 认证方式,添加手机号登录方式。
自定义身份认证类
utils/auth.py
,在项目中创建一个utils目录,自定义认证类
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import check_password
from django.db.models import Q
from user.models import User
# 自定义 认证类,需要在 settings.py 中指明配置项
class AuthBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
"""需要继承django内置的用户认证类,并重写认证方法,可以支持多种方式进行登录"""
try:
user = User.objects.get(Q(username=username) | Q(mobile=username))
except Exception as e:
return None
# 校验密码: 先写 需要校验的密码, 后写 加密后的密码
if check_password(password, user.password):
return user
else:
return None
指明配置项
在配置文件中,指明认证类
# 指定用户认证引擎
AUTHENTICATION_BACKENDS = [
'utils.auth.AuthBackend' , # 自己定义的认证类路径
]
--------------------------------------------------------------------------------------------------------------------------
退出登录
使用session会话保持的退出:
Vue前端
// 退出登录
logout() {
// 不显示退出登录框
this.visible = false;
this.$axios.post("/users/logout/").then((res) => {
console.log("@@退出登录的响应:", res);
if (res.data.code == 200) {
// 清空本地登录信息
// localStorage.setItem("user", "");
localStorage.removeItem("user");
// 清空vuex登录信息
this.setUser("");
this.notifySucceed("成功退出登录");
}else{
console.log("退出请求失败")
}
}).catch(err=>{return Promise.reject(err)})
},
django后端
#/users/logout/
path("logout/", Logout.as_view()),
#视图接口
class Logout(APIView):
def post(self, request):
print("会话保持:", request.session.items())
#前端Vue代理会处理sessionid的存储及Cookie信息的携带
#删除会话
if request.session.get("username"):
del request.session["username"]
print("再次查看session:", request.session.items())
return Response({"code":200, "msg":"ok"})
使用jwt会话保持的退出:
只需要 删除 localStorage中存储的token即可