1、在Django的子应用新建users/utils.py
文件编辑如下
"""
自定义用户传统身份认证的认证后端
目的:实现用户名或手机号,多账号登陆
"""
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q # Q将多个条件,构建成互为"或"的条件
from .models import User
# 继承Django默认的认证后端
class UsernameMobileAuthBackend(ModelBackend):
# 重写authenticate方法
# 原因:默认的authenticate方法,只会根据username字段去过滤查找用户
def authenticate(self, request, username=None, password=None, **kwargs):
# 允许多账号登陆的情况下,前端传来的"username"有可能是用户名也有可能是手机号
try:
# 1、先按用户名查找
user = User.objects.get(
# username=="18588269037" or mobile=="18588269037"
Q(username=username) | Q(mobile=username) | Q(email=username)
)
except User.DoesNotExist as e:
return None # 用户名找不到,返回None表示认证失败
# 3、某一个找到了,再校验密码
if user.check_password(password):
return user
2、修改配置文件dev.py
添加自定义认证后端
# 指定自定义的用户认证后端:
AUTHENTICATION_BACKENDS = [
'apps.users.utils.UsernameMobileAuthBackend'
]
3、当我们进行传统登录接口设计的时候,就可以直接使用全局身份认证函数authenticate
认证用户身份:
# 功能:验证用户名和密码 ---> 业务逻辑:通过用户名查找用户,再校验密码
# 参数:request请求对象,username用户名,password明文密码
# 返回值:用户名和密码校验成功返回用户对象,否则返回None
# 全局函数authenticate ---调用---> ModelBackend.authenticate实例方法完成用户名和密码校验
user = authenticate(request=request, username=username, password=password)
if user is None:
return JsonResponse({'code': 400, 'errmsg': '用户或密码输入有误'}, status=400)
4、登录视图接口代码:
# 传统登陆
class LoginView(View):
def post(self, request):
data = json.loads(request.body.decode())
username = data.get('username')
password = data.get('password')
remembered = data.get('remembered', False)
if not all([username, password, remembered]):
return JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})
if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
return JsonResponse({'code': 400, 'errmsg': '用户名格式错误'})
if not re.match(r'^\w{8,20}$', password):
return JsonResponse({'code': 400, 'errmsg': '密码格式有误'}, status=400)
# try:
# user = User.objects.get(username=username)
# except User.DoesNotExist as e:
# return JsonResponse({'code': 400, 'errmsg': '找不到用户,username写错误 或 没注册'})
#
# # 3.2、检查密码: User模型类对象继承自AbstractUser提供check_password函数用于校验明文密码
# if not user.check_password(password):
# return JsonResponse({'code': 400, 'errmsg': '密码输入有误'}, status=400)
user = authenticate(request=request, username=username, password=password)
if user is None:
return JsonResponse({'code': 400, 'errmsg': '用户或密码输入有误'}, status=400)
# 状态保持
login(request, user)
# 设置session数据有效期
if remembered != True:
request.session.set_expiry(0) # 有效期设置为0 —— 当用户关闭浏览器标签页则session失效
else:
request.session.set_expiry(None) # 使用django默认的14天有效期
response = JsonResponse({'code': 0, 'errmsg': 'OK'})
# 设置cookies
response.set_cookie(
'username',
user.username,
max_age=3600*24*14
)
return response
5、 使用cookie展示首页用户名–功能实现
(后端)用户登录和注册的时候, 都需要把用户的信息写入到 cookie.
生成响应对象
response = http.JsonResponse({'code':0, 'errmsg':'ok'})
在响应对象中设置用户名信息.
# 将用户名写入到 cookie,有效期 14 天
response.set_cookie('username', user.username, max_age = 3600 * 24 * 14)
# 返回响应结果
return response
(前端) 获取 cookie 信息, 进行页面展示
在 index.js 中:
下面涉及到前端代码, 我们不用添加.
data: {
// 添加一个变量, 从 cookie 中获取用户信息后
// 赋值给该变量
username: '',
},
mounted(){
// 获取 cookie 中的用户名
// getCookie 这个方法位于 base.js 文件中.
this.username = getCookie('username');
}
6、退出登录(清除状态保持)
django 给我们推出了一个 logout( ) 方法, 该方法正好和 login( ) 方法相反:
login() 函数, 可以把 user 信息, 写入到 session 中, 再把 sessionid 保存到 cookie 里.
logout() 函数则正好相反, 能够把 session 中的信息清除掉.
from django.contrib.auth import logout
# 用户退出登陆
class LogoutView(View):
def delete(self, request):
# 1、提取参数
# 2、校验参数
# 3、数据/业务处理
# 通过request--->获取cookie中的sessionid--->根据sessionid删除redis中的用户数据
logout(request)
# 4、构建响应
response = JsonResponse({'code': 0, 'errmsg': 'ok'})
response.delete_cookie('username')
return response