基本设置以及结果

功能描述

规划登录注册,以及submit提交按钮

将本地加载改为网页链接动态加载

代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. {% extends 'base.html'%}
  4. {% block content %}
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>登录</title>
  8. <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
  9. </head>
  10. <body>
  11. <h5>登录页面</h5>
  12. <div class="container">
  13. <div class="row">
  14. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  15. <form> {# action不再定义,基于Ajax提交 #}
  16. <div>
  17. <label for="">用户名</label>
  18. <input type="text" id="user"> {# ID用于Ajax获取信息 #}
  19. </div>
  20. <div>
  21. <label for="">密码</label>
  22. <input type="password" id="pwd">
  23. </div>
  24. <input type="button" class="btn btn-default login_btn"> {# login_btn用于绑定事件 #}
  25. </form>
  26. </div>
  27. </div>
  28. </div>
  29. </body>
  30. <% endblock%>
  31. </html>

实现效果

第一次新增

新增描述

预期实现页面居中显示

代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
  7. </head>
  8. <body>
  9. <h5>登录页面</h5>
  10. <div class="container">
  11. <div class="row">
  12. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  13. <form> {# action不再定义,基于Ajax提交 #}
  14. <div>
  15. <label for="">用户名</label>
  16. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  17. </div>
  18. <div>
  19. <label for="">密码</label>
  20. <input type="password" id="pwd" class="form-control">
  21. </div>
  22. <input type="button" class="btn btn-default login_btn" value="submit"> {# login_btn用于绑定事件 #}
  23. </form>
  24. </div>
  25. </div>
  26. </div>
  27. </body>
  28. </html>

第二次新增

设计功能: for与ID一致,可以在方框填入内容;设置submit提交按钮显示在右边

代码如下

代码

  1. <!DOCTYPE html>
  2. {% extends 'base.html' %}
  3. {% load static %}
  4. <html lang="en">
  5. {% block content %}
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>登录</title>
  9. </head>
  10. <body>
  11. <div class="container">
  12. <div class="row">
  13. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  14. <form> {# action不再定义,基于Ajax提交 #}
  15. <div>
  16. <label for="user">用户名</label>
  17. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  18. </div>
  19. <div>
  20. <label for="pwd">密码</label>
  21. <input type="password" id="pwd" class="form-control">
  22. </div>
  23. <input type="button" class="btn btn-default login_btn pull-right" value="submit"> {# login_btn用于绑定事件 #}
  24. </form>
  25. </div>
  26. </div>
  27. </div>
  28. </body>
  29. {% endblock %}
  30. </html>

第三次新增验证码

增加验证码区域,图片区域

代码

  1. <!DOCTYPE html>
  2. {% extends 'base.html' %}
  3. {% load static %}
  4. <html lang="en">
  5. {% block content %}
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>登录</title>
  9. </head>
  10. <body>
  11. <h1>Welcome to Blog of Caesar Tylor</h1>
  12. <div class="container">
  13. <div class="row">
  14. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  15. <form> {# action不再定义,基于Ajax提交 #}
  16. <div class="form-group">
  17. <label for="user">用户名</label>
  18. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  19. </div>
  20. <div class="form-group">
  21. <label for="pwd">密码</label>
  22. <input type="password" id="pwd" class="form-control">
  23. </div>
  24. <div>
  25. <label for="pwd">验证码</label>
  26. <div class="row">
  27. <div class="col-md-6">
  28. <input type="text" class="valid_code form-group">
  29. </div>
  30. <div class="col-md-6"></div>
  31. </div>
  32. </div>
  33. <input type="button" class="btn btn-default login_btn pull-right" value="submit">
  34. {# login_btn用于绑定事件 #}
  35. </form>
  36. </div>
  37. </div>
  38. </div>
  39. </body>
  40. {% endblock %}
  41. </html>

效果

第四次更改

静态生成验证码图片

代码

  1. <!DOCTYPE html>
  2. {% extends 'base.html' %}
  3. {% load static %}
  4. <html lang="en">
  5. {% block content %}
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>登录</title>
  9. </head>
  10. <body>
  11. <h1>Welcome to Blog of Caesar Tylor</h1>
  12. <div class="container">
  13. <div class="row">
  14. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  15. <form> {# action不再定义,基于Ajax提交 #}
  16. <div class="form-group">
  17. <label for="user">用户名</label>
  18. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  19. </div>
  20. <div class="form-group">
  21. <label for="pwd">密码</label>
  22. <input type="password" id="pwd" class="form-control">
  23. </div>
  24. <div>
  25. <label for="pwd">验证码</label>
  26. <div class="row">
  27. <div class="col-md-6">
  28. <input type="text" class="valid_code form-group">
  29. </div>
  30. <div class="col-md-6">
  31. <img width="240" height="30" src="https://tenfei05.cfp.cn/creative/vcg/800/new/VCG41N1210205351.jpg">
  32. </div>
  33. </div>
  34. </div>
  35. <input type="button" class="pull-right btn btn-default login_btn " value="submit" >
  36. {# login_btn用于绑定事件 #}
  37. </form>
  38. </div>
  39. </div>
  40. </div>
  41. </body>
  42. {% endblock %}
  43. </html>

效果

第五次更改

逐步改进,直到动态加载验证码

import PIL

pillow 官方文档 [Pillow — Pillow (PIL Fork) 8.3.1 documentation]

好看的配色 (234,255,211)

  1. 1. 解决思路,前端页面使用本地连接获取图片;需要URL配置链接, 需要在view视图中负责生成相应的资源
  2. ### 版本1:静态生成一个本地主项目下的图片,主要需要新引入两个包
  3. from django.shortcuts import render, HttpResponse, redirect
  4. def login(request):
  5. return render(request, "blog/login.html")
  6. def get_validCode_img(request):
  7. with open("smooth.jpg", "rb") as f:
  8. data = f.read()
  9. return HttpResponse(data)
  10. ### 版本2:生成随机颜色[磁盘存储]
  11. def get_validCode_img(request):
  12. # 第一种
  13. # with open("smooth.jpg", "rb") as f:
  14. # data = f.read()
  15. # 第二种方案
  16. def get_random_color():
  17. a = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
  18. return a
  19. img = Image.new("RGB", (240, 30), color=get_random_color())
  20. with open("smooth.png", "wb") as f:
  21. img.save(f, "png")
  22. with open("smooth.png", "rb") as f:
  23. data = f.read()
  24. return HttpResponse(data)
  25. ### 版本3:将颜色存储在内存,并且从中读取
  26. # 第三种方案
  27. from io import BytesIO
  28. def get_random_color():
  29. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  30. return a
  31. img = Image.new("RGB", (240,30), color=get_random_color())
  32. f = BytesIO()
  33. img.save(f,"png")
  34. data=f.getvalue()
  35. return HttpResponse(data)
  36. ### 版本4:生成可以验证码中的文字
  37. def get_validCode_img(request):
  38. # 第三种方案
  39. from io import BytesIO
  40. from PIL import Image, ImageDraw, ImageFont
  41. def get_random_color():
  42. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  43. return a
  44. img = Image.new("RGB", (240,30), color=get_random_color())
  45. draw = ImageDraw.Draw(img)
  46. kumo_font = ImageFont.truetype("static/font/kumo.ttf", 24)
  47. draw.text((0,5), "python", get_random_color(), font=kumo_font)
  48. # draw.line()
  49. # draw.point()
  50. f = BytesIO()
  51. img.save(f,"png")
  52. data=f.getvalue()
  53. return HttpResponse(data)
  54. ### 版本6 : 生成随机数字
  55. def get_validCode_img(request):
  56. # 第三种方案
  57. from io import BytesIO
  58. from PIL import Image, ImageDraw, ImageFont
  59. def get_random_color():
  60. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  61. return a
  62. img = Image.new("RGB", (240,30), color=get_random_color())
  63. draw = ImageDraw.Draw(img)
  64. kumo_font = ImageFont.truetype("static/font/FiraCode-Regular.ttf", size=24)
  65. for i in range(5):
  66. random_num = random.randint(0,9)
  67. random_low_alpha = chr(random.randint(95, 122)) # ASCⅡ大小写字母范围
  68. random_upper_alpha = chr(random.randint(65, 90))
  69. random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
  70. draw.text((i*50 + 20,5), str(random_char), get_random_color(), font=kumo_font) # 转换第二个参数的类型
  71. f = BytesIO()
  72. img.save(f,"png")
  73. data=f.getvalue()
  74. return HttpResponse(data)
  75. ### 版本7:增加噪点和噪线,增加机器识别难度
  76. def get_validCode_img(request):
  77. from io import BytesIO
  78. from PIL import Image, ImageDraw, ImageFont
  79. def get_random_color():
  80. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  81. return a
  82. img = Image.new("RGB", (240,30), color=get_random_color())
  83. draw = ImageDraw.Draw(img)
  84. kumo_font = ImageFont.truetype("static/font/FiraCode-Regular.ttf", size=24)
  85. for i in range(5):
  86. random_num = random.randint(0,9)
  87. random_low_alpha = chr(random.randint(95, 122)) # ASCⅡ大小写字母范围
  88. random_upper_alpha = chr(random.randint(65, 90))
  89. random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
  90. draw.text((i*50 + 20,5), str(random_char), get_random_color(), font=kumo_font) # 转换第二个参数的类型
  91. width = 250
  92. height = 40
  93. for i in range(10):
  94. x1 = random.randint(0, width)
  95. x2 = random.randint(0, width)
  96. y1 = random.randint(0, height)
  97. y2 = random.randint(0, height)
  98. draw.line((x1, x2, y1, y2), fill=get_random_color())
  99. for i in range(200):
  100. draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
  101. x = random.randint(0, width)
  102. y = random.randint(0, height)
  103. draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
  104. f = BytesIO()
  105. img.save(f,"png")
  106. data=f.getvalue()
  107. return HttpResponse(data)

第六次设置点击自动刷新验证码

实现逻辑分析

  1. 1. 引入Jquery文件
  2. 2. 登录源码中绑定事件,实现点击自动刷新

关联配置信息

  1. ### H5中的配置,修改第32行代码,增加ID,末尾使用script标签加载Jquery
  2. <!DOCTYPE html>
  3. {% extends 'base.html' %}
  4. {% load static %}
  5. <html lang="en">
  6. {% block content %}
  7. <head>
  8. <meta charset="UTF-8">
  9. <title>登录</title>
  10. </head>
  11. <body>
  12. <h1>Welcome to Blog of Caesar Tylor</h1>
  13. <div class="container">
  14. <div class="row">
  15. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  16. <form> {# action不再定义,基于Ajax提交 #}
  17. <div class="form-group">
  18. <label for="user">用户名</label>
  19. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  20. </div>
  21. <div class="form-group">
  22. <label for="pwd">密码</label>
  23. <input type="password" id="pwd" class="form-control">
  24. </div>
  25. <div>
  26. <label for="pwd">验证码</label>
  27. <div class="row">
  28. <div class="col-md-6">
  29. <input type="text" class="valid_code form-group">
  30. </div>
  31. <div class="col-md-6">
  32. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt="">
  33. </div>
  34. </div>
  35. </div>
  36. <input type="button" class="pull-right btn btn-default login_btn " value="submit" >
  37. {# login_btn用于绑定事件 #}
  38. </form>
  39. </div>
  40. </div>
  41. </div>
  42. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  43. {# <script src="C:/Users/41999/Documents/projectmanagement/Test/Scripts/whereabouts/static/js/jquery-3.6.0.min.js"></script>#}
  44. </body>
  45. {% endblock %}
  46. </html>
  47. ### browser调试代码
  48. $("#valid_code_img")[0]
  49. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt>
  50. $("#valid_code_img")[0].src+="?"
  51. "http://127.0.0.1:8001/get_validCode_img/?"
  52. $("#valid_code_img")[0].src+="??"
  53. "http://127.0.0.1:8001/get_validCode_img/???"
  54. $("#valid_code_img")[0].src+="??"
  55. "http://127.0.0.1:8001/get_validCode_img/?????"

网页调试过程

第七次 升级配置

保存原有配置

  1. <!DOCTYPE html>
  2. {% extends 'base.html' %}
  3. {% load static %}
  4. <html lang="en">
  5. {% block content %}
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>登录</title>
  9. </head>
  10. <body>
  11. <h1>Welcome to Blog of Caesar Tylor</h1>
  12. <div class="container">
  13. <div class="row">
  14. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  15. <form> {# action不再定义,基于Ajax提交 #}
  16. <div class="form-group">
  17. <label for="user">用户名</label>
  18. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  19. </div>
  20. <div class="form-group">
  21. <label for="pwd">密码</label>
  22. <input type="password" id="pwd" class="form-control">
  23. </div>
  24. <div>
  25. <label for="pwd">验证码</label>
  26. <div class="row">
  27. <div class="col-md-6">
  28. <input type="text" class="valid_code form-group">
  29. </div>
  30. <div class="col-md-6">
  31. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt="">
  32. </div>
  33. </div>
  34. </div>
  35. <input type="button" class="pull-right btn btn-default login_btn " value="submit" >
  36. {# login_btn用于绑定事件 #}
  37. </form>
  38. </div>
  39. </div>
  40. </div>
  41. {# <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>#}
  42. <script src="{% static '/static/js/jquery-3.6.0.min.js' %}"></script>
  43. <script>
  44. // 验证码图片刷新
  45. $("#valid_code_img").click(function(){
  46. $("this")[0].src+="?"
  47. })
  48. </script>
  49. </body>
  50. {% endblock %}
  51. </html>

升级后的配置

  1. <!DOCTYPE html>
  2. {% load static %}
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>登录</title>
  7. <link rel="stylesheet" href="{% static '/static/blog/bs/css/bootstrap.css' %}">
  8. </head>
  9. <body>
  10. <h1>Welcome to Blog of Caesar Tylor</h1>
  11. <div class="container">
  12. <div class="row">
  13. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  14. <form> {# action不再定义,基于Ajax提交 #}
  15. <div class="form-group">
  16. <label for="user">用户名</label>
  17. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  18. </div>
  19. <div class="form-group">
  20. <label for="pwd">密码</label>
  21. <input type="password" id="pwd" class="form-control">
  22. </div>
  23. <div>
  24. <label for="pwd">验证码</label>
  25. <div class="row">
  26. <div class="col-md-6">
  27. <input type="text" class="valid_code form-group">
  28. </div>
  29. <div class="col-md-6">
  30. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt="">
  31. </div>
  32. </div>
  33. </div>
  34. <input type="button" class="pull-right btn btn-default login_btn " value="submit" >
  35. {# login_btn用于绑定事件 #}
  36. </form>
  37. </div>
  38. </div>
  39. </div>
  40. <script src="{% static '/static/js/jquery-3.6.0.min.js' %}"></script>
  41. <script>
  42. $("#valid_code_img").click(function(){
  43. $(this)[0].src+="?"
  44. })
  45. </script>
  46. </body>
  47. </html>

二者区别

不再使用基文件和模板标签,直接使用资源引用中的静态文件模板标签,加载的内容减少了

第八次修改—-增加保存验证码的功能

后端支持代码

  1. from django.shortcuts import render, HttpResponse, redirect
  2. import PIL, random
  3. from django.http import JsonResponse
  4. from django.contrib import auth
  5. def login(request):
  6. """
  7. auth.login:在请求中保留用户id和后端。这样,用户就不必在每次请求时都重新验证。请注意,匿名会话期间的数据集在用户登录时保留。
  8. auth.authenticate: 从client请求中提取数据,将数据与数据库进行匹配
  9. response: 用一个字典作为message传递提示信息
  10. """
  11. if request.method=="POST":
  12. response = {"user":None,"msg":None}
  13. user = request.POST.get("user")
  14. print(user)
  15. pwd = request.POST.get("pwd")
  16. valid_code_one = request.POST.get("valid_code")
  17. valid_code = str(valid_code_one)
  18. valid_code_str = request.session.get("valid_code_str")
  19. # print(valid_code) 测试后端在提交前端显示之前保存的验证码
  20. # print(valid_code_str) 测试前端POST请求提交时给出的验证码
  21. if valid_code.upper() == valid_code_str.upper():
  22. user=auth.authenticate(username=user,password=pwd) # 将前端提交的密码与后端MySQL存储的用户名与密码匹配
  23. if user:
  24. auth.login(request,user) # 匹配成功后则将其注册request.user==当前登录对象,存储当前登录对象
  25. response["user"]=user.username
  26. else:
  27. response["msg"]="username or password error!"
  28. else:
  29. response["msg"] = "valide code error!"
  30. return JsonResponse(response)
  31. return render(request, "blog/login.html")
  32. def get_validCode_img(request):
  33. from io import BytesIO
  34. from PIL import Image, ImageDraw, ImageFont
  35. def get_random_color():
  36. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  37. return a
  38. img = Image.new("RGB", (240,30), color=get_random_color())
  39. draw = ImageDraw.Draw(img)
  40. kumo_font = ImageFont.truetype("static/font/FiraCode-Regular.ttf", size=24)
  41. valid_code_str = ""
  42. for i in range(5):
  43. random_num = random.randint(0,9)
  44. random_low_alpha = chr(random.randint(95, 122)) # ASCⅡ大小写字母范围
  45. random_upper_alpha = chr(random.randint(65, 90))
  46. random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
  47. draw.text((i*50 + 20,5), str(random_char), get_random_color(), font=kumo_font) # 转换第二个参数的类型
  48. # 保存验证码字符串
  49. valid_code_str+=str(random_char)
  50. width = 250
  51. height = 40
  52. for i in range(10):
  53. x1 = random.randint(0, width)
  54. x2 = random.randint(0, width)
  55. y1 = random.randint(0, height)
  56. y2 = random.randint(0, height)
  57. draw.line((x1, x2, y1, y2), fill=get_random_color())
  58. for i in range(200):
  59. draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
  60. x = random.randint(0, width)
  61. y = random.randint(0, height)
  62. draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
  63. # 打印保存的验证码
  64. # print("valid_code_str", valid_code_str)
  65. request.session["valid_code_str"]=valid_code_str
  66. """
  67. 1. 生成随机字符串
  68. 2. 设置一个cookie{sessionid:随机字符串}
  69. 3. django——session存储session_key---随机字符串,session_data---验证码
  70. """
  71. f = BytesIO()
  72. img.save(f,"png")
  73. data=f.getvalue()
  74. # print(type(data))
  75. return HttpResponse(data)
  76. def index(request):
  77. return render(request, "blog/index.html")

保存环境

  1. from django.shortcuts import render, HttpResponse, redirect
  2. import PIL, random
  3. def login(request):
  4. return render(request, "blog/login.html")
  5. def get_validCode_img(request):
  6. from io import BytesIO
  7. from PIL import Image, ImageDraw, ImageFont
  8. def get_random_color():
  9. a = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
  10. return a
  11. img = Image.new("RGB", (240,30), color=get_random_color())
  12. draw = ImageDraw.Draw(img)
  13. kumo_font = ImageFont.truetype("static/font/FiraCode-Regular.ttf", size=24)
  14. valid_code_str = ""
  15. for i in range(5):
  16. random_num = random.randint(0,9)
  17. random_low_alpha = chr(random.randint(95, 122)) # ASCⅡ大小写字母范围
  18. random_upper_alpha = chr(random.randint(65, 90))
  19. random_char = random.choice([random_num,random_low_alpha,random_upper_alpha])
  20. draw.text((i*50 + 20,5), str(random_char), get_random_color(), font=kumo_font) # 转换第二个参数的类型
  21. width = 250
  22. height = 40
  23. for i in range(10):
  24. x1 = random.randint(0, width)
  25. x2 = random.randint(0, width)
  26. y1 = random.randint(0, height)
  27. y2 = random.randint(0, height)
  28. draw.line((x1, x2, y1, y2), fill=get_random_color())
  29. for i in range(200):
  30. draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
  31. x = random.randint(0, width)
  32. y = random.randint(0, height)
  33. draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
  34. f = BytesIO()
  35. img.save(f,"png")
  36. data=f.getvalue()
  37. return HttpResponse(data)

修改后的代码

  1. <!DOCTYPE html>
  2. {% load static %}
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>登录</title>
  7. <link rel="stylesheet" href="{% static '/static/blog/bs/css/bootstrap.css' %}">
  8. </head>
  9. <body>
  10. <h1>Welcome to Blog of Caesar Tylor</h1>
  11. <div class="container">
  12. <div class="row">
  13. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  14. <form> {# action不再定义,基于Ajax提交 #}
  15. {% csrf_token %} {# 增加CSRF防护令牌 #}
  16. <div class="form-group">
  17. <label for="user">用户名</label>
  18. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  19. </div>
  20. <div class="form-group">
  21. <label for="pwd">密码</label>
  22. <input type="password" id="pwd" class="form-control">
  23. </div>
  24. <div class="form-group">
  25. {# for写错了 #}
  26. <label for="pwd">验证码</label>
  27. <div class="row">
  28. <div class="col-md-6">
  29. {# ID和class写到一起了 #}
  30. <input type="text" class="form-control" id="valid_code">
  31. </div>
  32. <div class="col-md-6">
  33. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt="">
  34. </div>
  35. </div>
  36. </div>
  37. <input type="button" class="btn btn-default login_btn pull-right" value="submit" >
  38. {# login_btn用于绑定事件 #}
  39. </form>
  40. </div>
  41. </div>
  42. </div>
  43. <script src="{% static '/static/js/jquery-3.6.0.min.js' %}"></script>
  44. <script>
  45. // 点击刷新验证码
  46. $("#valid_code_img").click(function(){
  47. $(this)[0].src+="?"
  48. });
  49. // 登录验证
  50. $(".login_btn").click(function(){
  51. $.ajax({
  52. url:"",
  53. type:"post",
  54. data:{
  55. user:$("#user").val(),
  56. pwd:$("#pwd").val(),
  57. valid_code:$("#valid_code").val(),
  58. csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
  59. },
  60. success:function(data){
  61. console.log(data);
  62. }
  63. })
  64. })
  65. </script>
  66. </body>
  67. </html>

修改过程

  1. 1. 构建Ajax事件,传递参数
  2. 1. 设计传递参数的内容,分别为用户,密码,验证码,csrf_token令牌
  3. 2. csrf_token令牌由模板标签产生,在浏览器前台源码中获得H5名称
  4. 2. 构建登录页面的重定向(在login.h5页面内)
  5. 1. 接收Ajax提交的数据,首先校验验证码[但不能将验证码改为全局变量直接校验,易在并发过程中被存储的其他用户的验证码覆盖]
  6. 2. 使用cookiesession会话技术
  7. 3. from django.http import JsonResponse,自动构建序列化,Ajax直接拿数据,无需反序列化
  8. 4. 逐次校验数据
  9. 3. 测试并且提交用户
  10. 1. 使用Ajax原地跳转并且提示错误信息
  11. 2. y

前台测试—验证码错误和验证码为空状态下的错误信息提示

MySQL中会话记录的查看

数据库表中存储的用户信息

测试用户信息提交

Ajax部分代码备份

  1. // 登录验证
  2. $(".login_btn").click(function(){
  3. $.ajax({
  4. url:"",
  5. type:"post",
  6. data:{
  7. user:$("#user").val(),
  8. pwd:$("#pwd").val(),
  9. valid_code:$("#valid_code").val(),
  10. csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
  11. },
  12. success:function(data){
  13. console.log(data);
  14. if(data.user){
  15. location.href="/index/"
  16. }
  17. else{
  18. $(".error").text(data.msg).css({"color":"red","margin-left":"10px"});
  19. }
  20. }
  21. })
  22. })

第九次修改—验证码代码优化

增加提示语自动消失的功能

  1. <script>
  2. // 点击刷新验证码
  3. $("#valid_code_img").click(function(){
  4. $(this)[0].src+="?"
  5. });
  6. // 登录验证
  7. $(".login_btn").click(function(){
  8. $.ajax({
  9. url:"",
  10. type:"post",
  11. data:{
  12. user:$("#user").val(),
  13. pwd:$("#pwd").val(),
  14. valid_code:$("#valid_code").val(),
  15. csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
  16. },
  17. success:function(data){
  18. // 将会在控制台打印log信息,据此可以判断获取信息是否全面准确
  19. console.log(data);
  20. if(data.user){
  21. location.href="/index/";
  22. {#window.location="index.html";#}
  23. }
  24. // 使得验证码错误的提示信息在一秒钟之后消失
  25. else{
  26. $(".error").text(data.msg).css({"color":"red","margin-left":"10px"});
  27. setTimeout(function(){
  28. $(".error").text("")
  29. },1000)
  30. }
  31. }
  32. })
  33. })
  34. </script>

极验滑动验证码的嵌入

  1. 1. 包准备
  2. social-auth-app-django==5.0.0
  3. social-auth-core==4.1.0

功能解耦

在blog下新建utlis文件夹,额外创建__init__.py文件夹

将随机数生成和验证码生成的功能独立解耦

view.py文件

  1. def get_validCode_img(request):
  2. from blog.utils.validCode import get_valide_code_img
  3. data = get_valide_code_img(request)
  4. # print(type(data))
  5. return HttpResponse(data)

前端login.html文件

  1. <!DOCTYPE html>
  2. {% load static %}
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>登录</title>
  7. <link rel="stylesheet" href="{% static '/static/blog/bs/css/bootstrap.css' %}">
  8. <link rel="shortcut icon" href="{% static 'static/blog/img/favicon.ico' %}" type="image/x-icon">
  9. </head>
  10. <body>
  11. <h3>Welcome to Blog of Caesar Tylor</h3>
  12. <div class="container">
  13. <div class="row">
  14. <div class="col-md-6 col-lg-offset-3"> {# 占用六个,右倾 #}
  15. <form> {# action不再定义,基于Ajax提交 #}
  16. {% csrf_token %} {# 增加CSRF防护令牌 #}
  17. <div class="form-group">
  18. <label for="user">用户名</label>
  19. <input type="text" id="user" class="form-control"> {# ID用于Ajax获取信息 #}
  20. </div>
  21. <div class="form-group">
  22. <label for="pwd">密码</label>
  23. <input type="password" id="pwd" class="form-control">
  24. </div>
  25. <div class="form-group">
  26. <label for="pwd">验证码</label>
  27. <div class="row">
  28. <div class="col-md-6">
  29. <input type="text" class="form-control" id="valid_code">
  30. </div>
  31. <div class="col-md-6">
  32. <img width="240" height="30" id="valid_code_img" src="/get_validCode_img/" alt="">
  33. </div>
  34. </div>
  35. </div>
  36. <input type="button" class="btn btn-default login_btn" value="submit" ><span class="error"></span>
  37. {# login_btn用于绑定事件 #}
  38. <a href="/registry/" class="btn btn-success pull-right">注册</a>
  39. </form>
  40. </div>
  41. </div>
  42. </div>
  43. <script src="{% static '/static/js/jquery-3.6.0.min.js' %}"></script>
  44. <script>
  45. // 点击刷新验证码
  46. $("#valid_code_img").click(function(){
  47. $(this)[0].src+="?"
  48. });
  49. // 登录验证
  50. $(".login_btn").click(function(){
  51. $.ajax({
  52. url:"",
  53. type:"post",
  54. data:{
  55. user:$("#user").val(),
  56. pwd:$("#pwd").val(),
  57. valid_code:$("#valid_code").val(),
  58. csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
  59. },
  60. success:function(data){
  61. // 将会在控制台打印log信息,据此可以判断获取信息是否全面准确
  62. console.log(data);
  63. if(data.user){
  64. location.href="/index/";
  65. {#window.location="index.html";#}
  66. }
  67. // 使得验证码错误的提示信息在一秒钟之后消失
  68. else{
  69. $(".error").text(data.msg).css({"color":"red","margin-left":"10px"});
  70. setTimeout(function(){
  71. $(".error").text("")
  72. },1000)
  73. }
  74. }
  75. })
  76. })
  77. </script>
  78. </body>
  79. </html>

valideCode.py

  1. # -*- coding: utf-8 -*-
  2. # @Time : 2021/8/25 9:53
  3. # @Author : 41999
  4. # @Email : 419997284@qq.com
  5. # @File : validCode.py
  6. # @Project : whereabouts
  7. from io import BytesIO
  8. from PIL import Image, ImageDraw, ImageFont
  9. import random
  10. def get_random_color():
  11. a = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
  12. return a
  13. def get_valide_code_img(request):
  14. img = Image.new("RGB", (240, 30), color=get_random_color())
  15. draw = ImageDraw.Draw(img)
  16. kumo_font = ImageFont.truetype("static/font/FiraCode-Regular.ttf", size=24)
  17. valid_code_str = ""
  18. for i in range(5):
  19. random_num = random.randint(0, 9)
  20. random_low_alpha = chr(random.randint(95, 122)) # ASCⅡ大小写字母范围
  21. random_upper_alpha = chr(random.randint(65, 90))
  22. random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
  23. draw.text((i * 50 + 20, 5), str(random_char), get_random_color(), font=kumo_font) # 转换第二个参数的类型
  24. # 保存验证码字符串
  25. valid_code_str += str(random_char)
  26. width = 250
  27. height = 40
  28. for i in range(10):
  29. x1 = random.randint(0, width)
  30. x2 = random.randint(0, width)
  31. y1 = random.randint(0, height)
  32. y2 = random.randint(0, height)
  33. draw.line((x1, x2, y1, y2), fill=get_random_color())
  34. for i in range(200):
  35. draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
  36. x = random.randint(0, width)
  37. y = random.randint(0, height)
  38. draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
  39. # 打印保存的验证码
  40. # print("valid_code_str", valid_code_str)
  41. request.session["valid_code_str"] = valid_code_str
  42. """
  43. 1. 生成随机字符串
  44. 2. 设置一个cookie{sessionid:随机字符串}
  45. 3. django——session存储session_key---随机字符串,session_data---验证码
  46. """
  47. f = BytesIO()
  48. img.save(f, "png")
  49. data = f.getvalue()
  50. return data

文件目录结构