文章目录
- 十、异步发送短信验证码 - 异步方案Celery
- 10.1 生产者消费者设计模式
- 10.2 Celery介绍
- 10.3 Celery介绍和使用
- 10.3.1
- 十一、用户账号 登录
- 11.1 用户登录
- 11.1.1 用户登录逻辑分析
- 11.1.2 用户登录接口设计和定义
- 11.1.3 用户登录后端逻辑
- 11.2 多账号登录
- 11.2.1 自定义用户认证的后端,实现多账号登录
- 11.2.2 开发环境配置文件dev.py
- 11.2.3 前端login.html文件
- 11.2.4 前端login.js文件
- 11.3 首页用户名显示
- 11.2.1 方案一:利用jinja2模板提供的变量和方法
- 11.2.2 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息
- 11.4 退出登录
- 11.4.1 Django用户认证系统logout()方法介绍
- 11.4.2 退出登录后端views.py
- 11.4.3 定义路由
- 11.4.4 前端index.html
- 11.5 判断用户是否登录(LoginRequiredMixin)
- 11.5.1 用户中心登录
- 11.5.2 开发配置文件定义LOGIN_URL
- 11.5.3 修改登录成功重定向指向
- 十二、QQ登录
- 12.1 QQ登录开发文档
十、异步发送短信验证码 - 异步方案Celery
10.1 生产者消费者设计模式
10.2 Celery介绍
Celery官方文档:https://docs.celeryproject.org/en/latest/index.html
Celery中文文档:http://docs.jinkan.org/docs/celery/
10.3 Celery介绍和使用
10.3.1
-
在项目根目录定义Celery包 celery_tasks
-
创建Celery实例
(meiduo_mall) PS E:\meiduo_project\meiduo_mall> celery -A celery_tasks.main worker -l info
十一、用户账号 登录
11.1 用户登录
11.1.1 用户登录逻辑分析
11.1.2 用户登录接口设计和定义
11.1.3 用户登录后端逻辑
class LoginView(View):
""" 用户登录 """
def get(self, request):
""" 提供用户登录页面 """
return render(request, 'login.html')
def post(self, request):
""" 实现用户登录逻辑 """
# 接收参数
username = request.POST.get('username')
password = request.POST.get('password')
rememebered = request.POST.get('rememebered')
# 校验参数
if not all([username, password]):
return http.HttpResponseForbidden('缺少必传参数')
if not re.match(r'^[a-zA-Z0-9-_]{5,20}$', username):
return http.HttpResponseForbidden('请输入正确的用户名或手机号!')
if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
return http.HttpResponseForbidden('密码8-20位!')
# 主体逻辑:认证用户(使用账号查询是否存在,账号存在再校验密码)、状态保持
user = authenticate(username=username, password=password)
if user is None:
return render(request, 'login.html', {'account_errmsg': '账号或密码错误!'})
# 状态保持
login(request, user)
# 使用remembered确定状态保持周期
if rememebered != 'on':
# 没有记住登录,状态保持在浏览器会话结束后销毁
request.session.set_expiry(0)
else:
# 记住登录,状态保持周期默认为两周(不要太长,以防攻击者,3600秒即可)
request.session.set_expiry(None)
# request.session.set_expiry(3600)
# 为了实现首页展示用户名,需要将用户名缓存到cookie
response = redirect(reverse('contents:index'))
response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
# 响应结果
return response
11.2 多账号登录
11.2.1 自定义用户认证的后端,实现多账号登录
users.utils.py文件
# 自定义用户认证的后端,实现多账号登录
from django.contrib.auth.backends import ModelBackend
import re
from meiduo_mall.apps.users.models import User
def get_user_by_account(account):
""" 通过账户(用户名或密码)获取用户 """
try:
if re.match(r'^1[3-9]\d{9}$', account):
# 匹配成功,account == 手机号
user = User.objects.get(mobile=account)
else:
# 匹配不成功,account == 用户名
user = User.objects.get(username=account)
except User.DoesNotExist:
return None
else:
return user
class UsernameMobileBackend(ModelBackend):
""" 自定义用户认证后端 """
def authenticate(self, request, username=None, password=None, **kwargs):
"""
重写用户认证方法
:param username:用户名或手机号
:param password:密码明文
:param kwargs:额外参数
:return :user
"""
# 查询用户
user = get_user_by_account(username)
# 如果可以查询到用户,还需要校验密码
if user and user.check_password(password):
# 返回user
return user
else:
return None
11.2.2 开发环境配置文件dev.py
# 指定自定义用户后端
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileBackend']
11.2.3 前端login.html文件
<div class="login_form_bg" id="app">
......
<form action="" method="post" class="login_form" @submit="on_submit" v-cloak>
{{ csrf_input }}
<input type="text" v-model="username" @blur="check_username" name="username">
<div v-show="error_username" class="user_error">请输入正确的用户名或手机号</div>
<input type="password" v-model="password" @blur="check_password" name="password">
<div v-show="error_password" class="pwd_error">密码8-20位</div>
{% if account_errmsg %}
<div class="pwd_error">{{ account_errmsg }}</div>
{% endif %}
<div class="more_input clearfix">
<input type="checkbox" v-model="remembered" name="remembered">
<label for="">记住登录</label>
</div>
<input type="submit" value="登 录" class="input_submit">
</form>
11.2.4 前端login.js文件
let vm = new Vue({
el: '#app',
// 修改Vue变量的读取语法
delimiters: ['[[', ']]'],
data: {
username: '',
password: '',
error_username: false,
error_password: false,
remembered: false,
},
methods: {
// 检查账号
check_username(username){
let re = /^[a-zA-Z0-9-_]{5,20}$/;
if (re.test(this.username)) {
this.error_username = false;
} else {
this.error_username = true;
}
},
// 检查密码
check_password(){
let re = /^[0-9a-zA-Z]{8,20}$/;
if (re.test(this.password)) {
this.error_password = false;
} else {
this.error_password = true;
}
},
//表单提交
on_submit(){
this.check_username();
this.check_password();
if (this.error_username == true || this.error_password == true) {
// 不满足登录条件
window.event.returnValue = false
}
},
// qq 登录
qq_login(){
let next = get_query_string('next') || '/';
let url = '/qq/login/?next=' + next;
axios.get(url, {
responseType: 'json'
})
.then(response => {
location.href = response.data.login_url;
})
.catch(error => {
console.log(error.response);
})
},
},
})
11.3 首页用户名显示
11.2.1 方案一:利用jinja2模板提供的变量和方法
最简单,只需要在index.html中调用jinja2模板的user变量的user.is_authenticated方法和user.username属性即可,但首页非静态页面
<!-- 方案一 :使用jinja2模板引擎自带的变量和方法,缺点:需要动态刷新页面,不符合首页静态页面的思想
使用jinjia2模板引擎自带user变量的自带方法判断 使用jinjia2模板引擎自带user变量渲染
{% if user.is_authenticated %}
<div class="login_btn fl">
欢迎您:<em>{{ user.username }}</em>
<span>|</span>
<a href="javascript:;" class="quit">退出</a>
</div>
{% else %}
<div class="login_btn fl">
<a href="login/">登录</a>
<span>|</span>
<a href="register/">注册</a>
</div>
{% endif %} -->
11.2.2 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息
index.html文件
<!-- 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息 -->
<div v-if="username" class="login_btn fl">
欢迎您:<em>[[ username ]]</em>
<span>|</span>
<a href="javascript:;" class="quit">退出</a>
</div>
<div v-else class="login_btn fl">
<a href="login/">登录</a>
<span>|</span>
<a href="register/">注册</a>
</div>
index.js文件
let vm = new Vue({
el: '#app',
delimiters:['[[', ']]'],
data:{
username: getCookie('username'),
f1_tab: 1, //1F标签页控制
f2_tab: 1, //2F标签页控制
f3_tab: 1, //3F标签页控制
// 渲染首页购物车数据
cart_total_count: 0,
carts: [],
},
common.js文件
//获取cookie
function getCookie(name) {
let r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
users.views.py后端用户登录和用户注册的最好,响应结果使用以下代码
# 为了实现首页展示用户名,需要将用户名缓存到cookie
response = redirect(reverse('contents:index'))
response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
# 响应结果
return response
11.4 退出登录
11.4.1 Django用户认证系统logout()方法介绍
原理:清理session和cookie
11.4.2 退出登录后端views.py
from django.contrib.auth import login, authenticate, logout
class LogoutView(View):
""" 用户退出登录 """
def get(self, request):
""" 实现用户退出登录的逻辑 """
# 清除状态保持信息
logout(request)
# 删除cookie中的用户名
response = redirect(reverse('contents:index'))
response.delete_cookie('username')
# 响应结果,重定向到首页
return response
11.4.3 定义路由
# 退出登录
path('logout/', views.LogoutView.as_view(), name='logout')
11.4.4 前端index.html
<!-- 方案二:静态首页展示后,使用Vue读取cookie局部渲染用户信息 -->
<div v-if="username" class="login_btn fl">
欢迎您:<em>[[ username ]]</em>
<span>|</span>
<!-- 使用jinja2模板的反向解析 -->
<a href="{{ url('users:logout') }}" class="quit">退出</a>
</div>
11.5 判断用户是否登录(LoginRequiredMixin)
应用场景:用户中心、订单系统,
Django用户认证系统提供了方法 request.user.is_authenticated() 来判断用户是否登录。如果通过登录验证则返回True,否则false。
LoginRequiredMixin封装了判断用户是否登录的操作。
11.5.1 用户中心登录
users.views.py
from django.contrib.auth.mixins import LoginRequiredMixin
class UserInfoView(LoginRequiredMixin, View):
""" 用户中心 """
def get(self, request):
""" 提供用户中心的页面 """
# if request.user.is_authenticated: # 判断用户是否登录的过程
# return render(request, 'user_center_info.html')
# else:
# return redirect(reverse('users:login'))
# login_url = reverse('/login/') # dev.py配置文件中已经指定 LOGIN_URL = '/login/'
# redirect_field_name = 'user_center_info.html' # LoginRequiredMixin有默认值next
return render(request, 'user_center_info.html')
11.5.2 开发配置文件定义LOGIN_URL
# 判断用户是否登录后,指定未登录用户重定向的地址
LOGIN_URL = '/login/'
11.5.3 修改登录成功重定向指向
users.views.py
# 根据发起登录请求的模块,登录成功重定向到不同的页面
next = request.GET.get('next')
if next: # LoginRequiredMixin的内置变量,存储登录要求来自哪里
response = redirect(next) # next存在,重定向到登录前模块页面
else:
response = redirect(reverse('contents:index')) # next不存在,重定向到首页
# 为了实现首页展示用户名,需要将用户名缓存到cookie
response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
# 响应结果,根据请求来源重定向
return response
十二、QQ登录
12.1 QQ登录开发文档
- QQ互联开发者申请步骤
相关链接:https://wiki.connect.qq.com/成为开发者
在QQ互联开放平台首页 https://connect.qq.com/ ,点击右上角的“登录”按钮,使用QQ帐号登录
公司认证,填写公司信息
2. QQ互联应用申请步骤
以下为演示图片,需要提前申请域名提供备案号,都必须是真实信息。
APP ID:101518219
APP KEY:418d84ebdc7241efb79536886ae95224
网站地址:www.meiduo.site
网站回调地址:http://www.meiduo.site:8000/oauth_callback
3. 网站对接QQ登录步骤
https://wiki.connect.qq.com/准备工作_oauth2-0
https://wiki.connect.qq.com/放置qq登录按钮_oauth2-0