Django+前端\django\myweb\blog\middleware\auth.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
import re
# 登录验证中间件
class AuthMiddleware(MiddlewareMixin):
"""中间件AuthMiddleware"""
def process_request(self, request):
# 假设我们想匹配以'/img/check_code/'开头的路径
path_info_regex = re.compile(r'^/img/check_code/')
# 使用match方法进行匹配
match = path_info_regex.match(request.path_info)
# print(request.path_info)
if match:
return
# 排除不需要中间件验证的页面
if request.path_info in ["/login/"]:
return
# 读取当彰访问的用户session的信息,如果能读到,说明已登陆过,就可以向后继续走
info_dict = request.session.get('info')
if info_dict:
# print(info_dict)
return
# 如果没有登录过,重定向到登录页面
return redirect("/login/")
# 中间件测试示例
class M1(MiddlewareMixin):
"""中间件M1"""
def process_request(self, request):
# 如果方法中没有返回值(返回None)
# 如果有返回值 HttpResponse、render、redirect,则不再继续向后执行,把返回值返回给用户
print("M1 进来了")
return HttpResponse("无权访问")
def process_response(self, request, response):
print("M1 出去了")
return response
class M2(MiddlewareMixin):
"""中间件M2"""
def process_request(self, request):
print("M2 进来了")
def process_response(self, request, response):
print("M2 出去了")
return response
Django+前端\django\myweb\myweb\settings.py
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware', # 放在最上面,重写了response
'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',
'blog.middleware.auth.AuthMiddleware',
# 'blog.middleware.auth.M1',
# 'blog.middleware.auth.M2',
'django.middleware.cache.FetchFromCacheMiddleware' # 放在最下面,重写了request
]
Django+前端\django\myweb\blog\utils\check_code.py
import random, string
from PIL import Image, ImageDraw, ImageFont, ImageFilter
def check_code(width=120, height=30, char_length=5, font_file='D:\\git-python\\前端\\django\\myweb\\blog\\utils\\ttf\\kumo.ttf', font_size=28):
code = []
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
def rndChar():
"""
生成随机字母
:return:
"""
# return chr(random.randint(65, 90)) # 随机 ascii 码大写字母范围
return random.choice(string.ascii_letters) # 随机大小写字母
# return str(random.randint(0, 9)) # 随机0-9的数字字符串
def rndColor():
"""
生成随机颜色
:return:
"""
return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
# 写文字
font = ImageFont.truetype(font_file, font_size)
for i in range(char_length):
char = rndChar()
code.append(char)
h = random.randint(0, 4)
draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
# 写干扰点
for i in range(18):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
# 写干扰圆圈
for i in range(18):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
# 画干扰线
for i in range(5):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=rndColor())
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img,''.join(code)
if __name__ == '__main__':
# 1. 直接打开
img,code = check_code()
img.show()
# 2. 写入文件
# img,code = check_code()
# with open('code.png','wb') as f:
# img.save(f,format='png')
# 3. 写入内存(Python3)
# from io import BytesIO
# stream = BytesIO()
# img.save(stream, 'png')
# stream.getvalue()
# 4. 写入内存(Python2)
# import StringIO
# stream = StringIO.StringIO()
# img.save(stream, 'png')
# stream.getvalue()
pass
Django+前端\django\myweb\blog\utils\password.py
import string
import re
def check_fips_password_complexity(password):
# 验证密码长度
if len(password) < 8:
return "密码长度不合格,不低于8位"
# 定义字符集
uppercase_letters = string.ascii_uppercase
lowercase_letters = string.ascii_lowercase
digits = string.digits
special_chars = string.punctuation.replace("?", "") # 假设 ? 是不允许的特殊字符
# 检查各个字符集是否至少出现一次
if not any(char in uppercase_letters for char in password):
return "密码必须包含至少一个大写字母"
if not any(char in lowercase_letters for char in password):
return "密码必须包含至少一个小写字母"
if not any(char in digits for char in password):
return "密码必须包含至少一个数字"
if not any(char in special_chars for char in password):
return "密码必须包含至少一个特殊字符"
# 检查密码是否包含不允许的字符
if re.search(r'[\s\x00]', password):
return "密码包含不允许的字符(空格、中止字符等)"
# print("密码符合FIPS复杂度要求")
return True
# 使用示例
if __name__ == "__main__":
password = "Example1="
str = check_fips_password_complexity(password)
print(str)
Django+前端\django\myweb\blog\views\account.py
from django.shortcuts import render, redirect
from blog.models import Admin
from blog.utils.form import LoginForm
# from blog.utils.form import LoginModelForm
from django.http import HttpResponse,HttpResponseRedirect
from blog.utils.check_code import check_code
from io import BytesIO
# 用户登录
def login(request):
# form
if request.method == "GET":
form = LoginForm()
context = {
"form": form,
}
return render(request, "login.html", context)
form = LoginForm(data=request.POST)
if form.is_valid():
# 获取用户输入的验证码,使用pod获取,并剔除code,再进行下一步数据校验,数据库没有code数据。
user_input_code = form.cleaned_data.pop('code')
# 获取用户session内image_code值
image_code = request.session.get('image_code', "")
# 区分大小写
# if user_input_code == image_code:
# 不区分大小写
if user_input_code.upper() != image_code.upper():
form.add_error("code", "验证码错误!")
context = {
"form": form,
}
return render(request, "login.html", context)
# 数据提交验证成功,获取到输入的用户名和密码
# print(form.cleaned_data) # {'username': 'tang', 'password': 'Tang@1234'}
# form 里进行 clean_password 数据处理后返回密码存储的md5值去数据库进行比对
# print(form.cleaned_data) # {'username': 'tang', 'password': '469bb5f078060211a9e6a2a5459bda16'}
# 数据库数据查询比对
# admin_object = Admin.objects.filter(username=form.cleaned_data['username'],password=form.cleaned_data['password']).first()
# 如果数据字段与数据库表字段名一致
# admin_object = Admin.objects.filter(**form.cleaned_data).first()
user_object = Admin.objects.filter(username=form.cleaned_data['username']).first()
admin_object = Admin.objects.filter(username=form.cleaned_data['username'],password=form.cleaned_data['password']).first()
# if not Admin_object:
# form.add_error("username", "用户名或者密码错误!")
# form.add_error("password", "用户名或者密码错误!")
# context = {
# "form": form,
# }
# return render(request, "login.html", context)
if not user_object:
form.add_error("username", "用户名错误!")
context = {
"form": form,
}
return render(request, "login.html", context)
elif not admin_object:
form.add_error("password", "密码错误!")
context = {
"form": form,
}
return render(request, "login.html", context)
else:
# 用户名与密码正确
# 网站生成随机字符串;写到用户浏览器的cookie中;再写入到session中
""" COOKIES
# 例子1:不使用模板
response = HttpResponse("hello world")
response.set_cookie(key,value,max_age)
return response
# 例子2: 使用模板
response = render(request,'xxx.html', context)
response.set_cookie(key,value,max_age)
return response
# 例子3: 重定向
response = HttpResponseRedirect('/login/')
response.set_cookie(key,value,max_age)
return response
# 删除
response.delete_cookie('username')
# 获取 COOKIES值
# 方法一
request.COOKIES['username']
# 方法二
request.COOKIES.get('username','')
# 判断是否存在
request.COOKIES.has_key('cookie_name')
"""
""" session
# 设置session的值
request.session['key'] = value
request.session.set_expiry(time): 设置过期时间, 0表示浏览器关闭则失效
# 获取session的值
request.session.get('key', None)
# 判断一个key是否在session里
'fav_color' in request.session
# 获取所有session的key和value
request.session.keys()
request.session.values()
request.session.items()
# 清除所有session
request.session.clear() # 只删除session中值得部分
# 删除所有session
# request.session.flush() # 删除session中的整条记录
# 删除key为age的session
del request.session["age"]
"""
response = HttpResponseRedirect('/admin_list/')
# 将username写入浏览器cookie,有效时间为360秒
response.set_cookie('id', admin_object.id, 3600)
response.set_cookie('name', admin_object.username, 3600)
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# request.session.set_expiry(1209600) # 默认 1209600 14天
request.session.set_expiry(60 * 60 * 24 * 7) # 7天
# 删除key为image_code的session,防止验证码复用
del request.session["image_code"]
return response
context = {
"form": form,
}
return render(request, "login.html", context)
# 用户登录注销
def loginout(request):
""" 注销 """
# 清除当前session
request.session.clear()
return redirect("/login/")
# 图片验证码
def check_code_img(request, random):
"""生成图片验证码"""
# 调用pillow函数,生成图片
# from blog.utils.check_code import check_code
img, code_string = check_code(width=120, height=30, char_length=5, font_file='D:\\git-python\\Django+前端\\django\\myweb\\blog\\utils\\ttf\\kumo.ttf', font_size=28)
# img.show()
# print(code_string)
# code_string 写入到自己的session中,以便于后续获取验证码再进行校验
request.session['image_code'] = code_string
# 设置session 超时时间为 60s
request.session.set_expiry(60)
# 写入内存(Python3)
# from io import BytesIO
stream = BytesIO()
img.save(stream, 'png')
# stream.getvalue()
return HttpResponse(stream.getvalue())
Django+前端\django\myweb\myweb\urls.py
urlpatterns = [
# 图片验证码
path('img/check_code/', account.check_code_img),
re_path(r'img/check_code/(?P<random>\d+)', account.check_code_img), # 点击刷新验证码
]
Django+前端\django\myweb\blog\templates\login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>员工管理系统-登录</title>
{% load static %}
<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>
<div class="panel-body">
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名</label>
{{ form.username }}
<span style="color: red;">{{ form.errors.username.0 }}</span>
</div>
<div class="form-group">
<label>密码</label>
{{ form.password }}
<span style="color: red;">{{ form.errors.password.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.errors.code.0 }}</span>
</div>
<div class="col-xs-5">
<img id="image_code" src="/img/check_code/666" onclick="change_img()" title="点击换验证码">
</div>
</div>
</div>
<button type="submit" class="btn btn-primary center-block" style="width: 80px;">登录</button>
</form>
</div>
</div>
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
<script>
function change_img() {
var img = document.getElementById("image_code");
img.src= '/img/check_code/'+(new Date()).getTime();
}
</script>
</body>
</html>