欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
1. 什么是cookie和session
1.1 cookie
-
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。
-
简单理解:一个服务器给用户的id凭证,靠着这个id服务器认证用户。
1.2 session
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
- 简单理解:一个服务器
2. 管理员登录login基本流程实现
2.1 url.py
path('login/', account.login),
2.2 account.py
因为之前一直用moudleForm这次练习一下form
class LoginForm(BootStrapForm):
username = forms.CharField(
label="用户名",
widget=forms.TextInput,
required=True
)
password = forms.CharField(
label="密码",
widget=forms.PasswordInput(render_value=True),
required=True
)
def clean_password(self):
pwd = self.cleaned_data.get("password")
return md5(pwd)
def login(request):
""" 登录 """
if request.method == "GET":
form = LoginForm()
return render(request, 'login.html', {'form': form})
form = LoginForm(data=request.POST)
if form.is_valid():
# 验证成功,获取到的用户名和密码
# {'username': 'wupeiqi', 'password': '123',"code":123}
# {'username': 'wupeiqi', 'password': '5e5c3bad7eb35cba3638e145c830c35f',"code":xxx}
# 去数据库校验用户名和密码是否正确,获取用户对象、None
# admin_object = models.Admin.objects.filter(username=xxx, password=xxx).first()
admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
if not admin_object:
form.add_error("password", "用户名或密码错误")#表示在password字段下添加错误信息
# form.add_error("username", "用户名或密码错误")#表示在username字段下添加错误信息
return render(request, 'login.html', {'form': form})
# 用户名和密码正确
# 网站生成随机字符串; 写到用户浏览器的cookie中;在写入到session中;
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# session可以保存7天
request.session.set_expiry(60 * 60 * 24 * 7)
return redirect("/admin/list/")
return render(request, 'login.html', {'form': form})
2.3 layout.html
给原来的登录加上login.html的超链接
<li><a href="/login">登录</a></li>
2.4 login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
<style>
.account {
width: 400px;
border: 1px solid #dddddd;
border-radius: 5px;
box-shadow: 5px 5px 20px #aaa;
margin-left: auto;
margin-right: auto;
margin-top: 100px;
padding: 20px 40px;
}
.account h2 {
margin-top: 10px;
text-align: center;
}
</style>
</head>
<body>
<div class="account">
<h2>用户登录</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名</label>
{{ form.username }}
<span style="color: red;">{{ form.username.errors.0 }}</span>
</div>
<div class="form-group">
<label>密码</label>
{{ form.password }}
<span style="color: red;">{{ form.password.errors.0 }}</span>
</div>
<div class="form-group">
<label for="id_code">图片验证码</label>
<div class="row">
<div class="col-xs-7">
{{ form.code }}
<span style="color: red;">{{ form.code.errors.0 }}</span>
</div>
<div class="col-xs-5">
<img id="image_code" src="/image/code/" style="width: 125px;">
</div>
</div>
</div>
<input type="submit" value="登 录" class="btn btn-primary">
</form>
</div>
</body>
</html>
2.5 登录前注意,数据库中的密码一定得是md5
否则会无法登录,可以用重置密码的方式把一般密码改为md5密码
3. cookie和session实现
3.1 视图验证登陆成功后增加 session
登陆成功后session中会有一个info值
# 用户名和密码正确
# 网站生成随机字符串; 写到用户浏览器的cookie中;在写入到session中;
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# session可以保存7天
request.session.set_expiry(60 * 60 * 24 * 7)
完整代码
def login(request):
""" 登录 """
if request.method == "GET":
form = LoginForm()
return render(request, 'login.html', {'form': form})
form = LoginForm(data=request.POST)
if form.is_valid():
# 验证成功,获取到的用户名和密码
# {'username': 'wupeiqi', 'password': '123',"code":123}
# {'username': 'wupeiqi', 'password': '5e5c3bad7eb35cba3638e145c830c35f',"code":xxx}
# 去数据库校验用户名和密码是否正确,获取用户对象、None
# admin_object = models.Admin.objects.filter(username=xxx, password=xxx).first()
admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
if not admin_object:
form.add_error("password", "用户名或密码错误")#表示在password字段下添加错误信息
# form.add_error("username", "用户名或密码错误")#表示在username字段下添加错误信息
return render(request, 'login.html', {'form': form})
# 用户名和密码正确
# 网站生成随机字符串; 写到用户浏览器的cookie中;在写入到session中;
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# session可以保存7天
request.session.set_expiry(60 * 60 * 24 * 7)
return redirect("/admin/list/")
return render(request, 'login.html', {'form': form})
3.2 鉴权,访问权限
以管理员列表为例,假设管理员登录了才能看管理员列表,在admin_list开头加上简单的鉴权
def admin_list(request):
""" 管理员列表 """
# 简单的鉴权
info=request.session.get('info')#尝试获取info值,如果获取失败返回false
if not info:
return redirect('/login')#跳转到登录页面
3.3 引入中间件
-
我们当然不可能在每个视图函数前cv上面这3行的简单鉴权,妥妥的代码冗余,有没有一种方法可以批量在指定的视图之前加上鉴权呢?
-
中间件可以成为勤奋的函数,在所有方法之前就执行。
/image/code/
与后面的验证码有关,可以不写。
4. 中间件
4.1 中间件的request
在中间件的process_request方法
# 如果方法中没有返回值(返回None),继续向后走
# 如果有返回值 HttpResponse、render 、redirect,则不再继续向后执行。
4.2 如何应用中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.middleware.auth.AuthMiddleware',
]
项目结构如下:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
class AuthMiddleware(MiddlewareMixin):
#中间件的请求
def process_request(self, request):#在所有方法之前执行
# 排除那些不需要登录就能访问的页面,不排除的话 在登录页面也要返回登录页面陷入循环
# request.path_info 获取当前用户请求的URL /login/
if request.path_info in ["/login/", "/image/code/"]:#如果已经在登录界面或者code界面
return
# 读取当前访问的用户的session信息,如果能读到,说明已登陆过,就可以继续向后走。
info_dict = request.session.get("info")
# print(info_dict)
if info_dict:
return
# 没有登录过,重新回到登录页面
return redirect('/login/')
#中间件的返回
# def process_response(self, request, response):
# print("M2.process_response")
# return response
6. 管理员注销
6.1 url.py
path('logout/', account.logout),
6.2 account.py
主要是清除掉session
def logout(request):
""" 注销 """
request.session.clear()#清除session
return redirect('/login/')
6.3 layout.html
<li><a href="/logout/">注销</a></li>
7. 导航栏的用户名与登录的用户名统一
我们之前的这个位置用户名是写死的,现在要和登录用户
获取session中的数据
{{ request.session.info.name }}
总结
大家喜欢的话,给个👍,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2023 mzh
Crated:2023-3-1
欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
『01. 安装配置Django』
『02. 创建并运行一个Django项目』
『03. 初识Django』
『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
『05. 数据库操作,实战用户管理』
『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
『07. 模板语法』
『08. 实战项目:部门和员工管理系统(01)』
『09. 实战项目:员工编辑删除功能与靓号管理(02)』
『10. 实战项目:靓号搜索功能(03)』
『11. 实战项目:分页与页码跳转功能(04)』
『12. 实战项目:分页组件的封装 面向接口编程(05)』
『13. 实战项目:添加用户时的时间选择组件(06)』
『14. 实战项目:一些面向对象的代码结构优化(07)』
『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
『16. 实战项目:BootStrap类的进一步优化(09)』
『17. 实战项目:login业务涉及cookie、session、中间件(10)』
『18. 实战项目:登录时的验证码(11)』
『19. 实战项目:初识Ajax请求(12)』
『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
『21. 实战项目:echart数据图表(14)』
『22. 实战项目:简单的文件上传(15)』
『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
【更多内容敬请期待】