2 基于用于认证组件 & ajax实现登录验证(图片验证码)
1 登录页面
settings.py
INSTALLED_APPS = [
...
'blog.apps.BlogConfig',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'root123', # 数据库用户密码
'NAME': 'cnblog' # 数据库名字
}
}
STATIC_URL = '/static/'
# ============= 自个配置 ==============
AUTH_USER_MODEL = 'blog.UserInfo'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
urls.py
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
]
views.py
from django.shortcuts import render
def login(request):
return render(request, 'login.html')
login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'blog/css/bootstrap.css' %}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>登录页面</h3>
<form>
<div class="form-group">
<label for="user">用户名</label>
<input type="text" id="user" class="form-control">
</div>
<div class="form-group">
<label for="pwd">密码</label>
<input type="password" id="pwd" class="form-control">
</div>
<div class="form-group">
<label for="pwd">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="valid_code">
</div>
<div class="col-md-6">
<img src="/get_validCode_img/" id="valid_code_img" width="260" height="32">
</div>
</div>
</div>
<input type="button" class="btn btn-default login_btn pull-right" value="登录">
</form>
</div>
</div>
</div>
</body>
</html>
2 随机验证码实现
views.py
from django.shortcuts import render, HttpResponse, redirect
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random
def get_random_color():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
def get_validCode_img(request):
# 方式1:
# with open('lulu.jpg', 'rb') as f:
# data = f.read()
# return HttpResponse(data)
# 方式2:pip install pillow
# 磁盘管理
# img = Image.new("RGB", (260, 32), color=get_random_color())
# with open('validCode.png', 'wb') as f:
# img.save(f, 'png')
#
# with open('validCode.png', 'rb') as f:
# data = f.read()
# return HttpResponse(data)
# 方式3:
# 内存管理
# img = Image.new("RGB", (260, 32), color=get_random_color()) # 图片句柄
# f = BytesIO # 内存句柄(使用完就会清除掉)
# img.save(f, 'png')
# data = f.getvalue()
# return HttpResponse(data)
# 方式4:面板里加内容
# 内存管理
img = Image.new("RGB", (260, 32), color=get_random_color()) # 图片句柄
draw = ImageDraw.Draw(img) # 生成画笔
font_obj = ImageFont.truetype('static/blog/font/aigei_com.ttf', size=20) # 字体样式的路径
for i in range(5):
random_num = str(random.randint(0, 9)) # 生成随机数字
random_low_alpha = chr(random.randint(95, 122)) # 生成随机小写字母
random_upper_alpha = chr(random.randint(65, 90)) # 生成随机大写字母
random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
draw.text((i * 50+20, 5), random_char, get_random_color(), font=font_obj) # 写文件
# draw.line() # 画线
# draw.point() # 画点
width, height = 260, 40 # 设置图片的宽高
for i in range(10): # 造10个线
x1 = random.randint(0, width)
x2 = random.randint(0, width)
y1 = random.randint(0, height)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=get_random_color())
for i in range(10): # 造10个点
draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
f = BytesIO() # 内存句柄(使用完就会清除掉)
img.save(f, 'png')
data = f.getvalue()
return HttpResponse(data)
def login(request):
return render(request, 'login.html')

3 点击验证码刷新
根据以上login.html代码,在加入js代码即可
login.html
<script src="{% static 'blog/js/jquery-3.6.0.min.js' %}"></script>
<script>
$("#valid_code_img").click(function () {
$(this)[0].src += "?"
})
</script>
4 验证码的存储
如果多人登录,那么验证码只能使最后一个人登录成功。这显然是有问题的,那么我们怎么解决呢?
解决方法:使用session,每个用户都有自己的session验证码。
views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import random
# Create your views here.
def get_random_color():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
def get_validCode_img(request):
...
request.session["valid_code_str"] = valid_code_str # 将验证码存入用户session中
'''
session过程:
1.生成一个随机的字符串 "asdfasdfsfsd"
2.COOKIE {'session_id': asdfasdfsfsd}
3.在django-session表中生成
session-key session-data
asdfasdfsfsd {"valid_code_str": "xxxx"}
'''
f = BytesIO() # 内存句柄(使用完就会清除掉)
img.save(f, 'png')
data = f.getvalue()
return HttpResponse(data)
def login(request):
if request.method == "POST":
response = {'user': None, 'msg': None}
user = request.POST.get('user')
pwd = request.POST.get('pwd')
valid_code = request.POST.get('valid_code')
valid_code_str = request.session.get("valid_code_str")
if valid_code.upper() == valid_code_str.upper():
pass
else:
response['msg'] = "valid code error!"
return JsonResponse(response) # 使用JsonResponse返回的数据,前端直接可以使用。
return render(request, 'login.html')
5 登录验证
views.py
from django.shortcuts import render
from django.http import JsonResponse
from django.contrib import auth
...
def login(request):
if request.method == "POST":
response = {'user': None, 'msg': None}
user = request.POST.get('user')
pwd = request.POST.get('pwd')
valid_code = request.POST.get('valid_code')
valid_code_str = request.session.get("valid_code_str", '')
if not valid_code.upper() == valid_code_str.upper():
response['msg'] = "valid code error!"
return JsonResponse(response)
user = auth.authenticate(username=user, password=pwd)
if not user:
response['msg'] = "username or password error!"
return JsonResponse(response)
auth.login(request, user) # request.user == 当前登录对象
response['user'] = user.username
return JsonResponse(response) # 使用JsonResponse返回的数据,前端直接可以使用。
return render(request, 'login.html')
def index(request):
return render(request, 'index.html')
login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'blog/bootstrap/css/bootstrap.css' %}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>登录页面</h3>
<form>
{% csrf_token %}
<div class="form-group">
<label for="user">用户名</label>
<input type="text" id="user" class="form-control">
</div>
<div class="form-group">
<label for="pwd">密码</label>
<input type="password" id="pwd" class="form-control">
</div>
<div class="form-group">
<label for="pwd">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="valid_code">
</div>
<div class="col-md-6">
<img src="/get_validCode_img/" id="valid_code_img" width="260" height="32">
</div>
</div>
</div>
<input type="button" class="btn btn-default login_btn pull-right" value="登录">
<span class="error" style="color: red"></span>
</form>
</div>
</div>
</div>
<script src="{% static 'blog/js/jquery-3.6.0.min.js' %}"></script>
<script>
// 刷新验证码
$("#valid_code_img").click(function () {
$(this)[0].src += "?"
});
// 登录验证
$('.login_btn').click(function () {
$.ajax({
url: '',
type: "post",
data: {
user: $('#user').val(),
pwd: $('#pwd').val(),
valid_code: $('#valid_code').val(),
csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
},
success: function (res) {
if (res.user) {
location.href='/index/'
}else {
$('.error').text(res.msg)
}
}
})
})
</script>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>首页</h3>
<div>当前登录用户:{{ request.user.username }}</div>
</body>
</html>

浙公网安备 33010602011771号