博客园项目-登录(验证码,ajax提交数据,session和cookie)

前端页面

{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    <link rel="stylesheet" href="{% static ‘bootstrap-3.3.7/css/bootstrap.min.css‘ %}">
    <style>
        body {
            background-color: #eeeeee;
        }
        h3{
            padding-left: 100px;
        }
        .container{
            margin-top: 300px;
        }
    </style>
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3>请登录</h3>
            <form class="form-horizontal">
                {% csrf_token %}
                <div class="form-group">
                    <label for="inputUser" class="col-sm-2 control-label">账号</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="inputUser" placeholder="账号">
                        <span class="help-block"></span>
                    </div>
                </div>
                <div class="form-group">
                    <label for="inputPassword" class="col-sm-2 control-label">密码</label>
                    <div class="col-sm-10">
                        <input type="password" class="form-control" id="inputPassword" placeholder="Password">
                        <span class="help-block"></span>
                    </div>
                </div>

                <div class="form-group">
                    <label for="valid_code" class="col-sm-2 control-label">验证码</label>
                    <div class="col-sm-5">
                        <input type="text" class="form-control" id="valid_code" placeholder="验证码">
                        <span class="help-block"></span>
                    </div>
                    <div class="col-sm-5">
                        <img src="/get_valid_img/"  width="200" height="40">
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <input type="button" class="btn btn-primary btn-lg btn-block" value="登录">
                        <span></span>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

<script src="{% static ‘jquery-3.2.1.min.js‘ %}"></script>
<script src="{% static ‘bootstrap-3.3.7/js/bootstrap.min.js‘ %}"></script>
<script>

    $(":button").click(function () {
        $.ajax({
            url:"/login/",
            type:"post",
            data:{
                "user":$("#inputUser").val(),
                "pwd":$("#inputPassword").val(),
                "valid_code": $("#valid_code").val(),
                "csrfmiddlewaretoken":$("[name=‘csrfmiddlewaretoken‘]").val()
            },
            success: function (data) {
                var data = JSON.parse(data);
                if (data.is_login){
                    location.href="/index/"
                }else{
                    $(":button").next().text(data.error_msg).css("color","red")
                    setTimeout(function () {
                        $(":button").next().text("")
                    },1000)
                }
            }
        })
    })

</script>
</body>
</html>

可以看到用户访问登录页面时,在求情验证码图片时会访问/get_valid_img/,通过该url来得到验证码图片

用户的数据通过ajax提交到后端,当后端完成验证后,如果验证成后,则跳转到首页,如果失败,则将错误信息添加到页面上

生成随机验证码

def get_valid_img(request):
    # from utils.random_code import get_random_code  # 局部模块导入不能用*
    # data = get_random_code()
    import random

    def get_random_color():
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    # 方式1:
    # f = open("car.jpg", "rb")
    # data = f.read()
    # f.close()

    # 方式2:将图片存到磁盘
    # import PIL
    # from PIL import Image
    # from io import BytesIO
    # image = Image.new(mode="RGB", size=(120, 80), color=get_random_color())
    # f = open("code.png", "wb")
    # image.save(f, "png")
    # f.close()
    # f = open("code.png", "rb")
    # data = f.read()
    # f.close()

    # 方式3:将图片放到内存
    # import PIL
    # from PIL import Image
    # from io import BytesIO
    # image = Image.new(mode="RGB", size=(120, 80), color=get_random_color())
    # f = BytesIO()
    # image.save(f, "png")
    #
    # data = f.getvalue()

    # 方式4:
    from PIL import Image  # PIL模块可以通过下载pillow模块使用
    from io import BytesIO
    from PIL import ImageDraw, ImageFont  # 画笔
    image = Image.new(mode="RGB", size=(120, 80), color=get_random_color())
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)
    temp = []
    for i in range(5):
        random_char = random.choice(
            [chr(random.randint(65, 90)), chr(random.randint(97, 122)), str(random.randint(0, 9))])
        draw.text((i * 24, 20), random_char, get_random_color(), font=font)  # 参数分别为坐标,添加的字符串,颜色,字体
        temp.append(random_char)
        # 为了让生成的验证码更具迷惑性,我们可以使用下面的方法给验证码图片中增加随机的点线等
    # for i in range(80):
    #     draw.point((random.randint(0,width),random.randint(0,height)),fill=get_random_color())
    #
    # for i in range(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(40):
    #     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()
    image.save(f, "png")

    data = f.getvalue()
    # 保存随机字符串
    random_code_str = "".join(temp)
    request.session["random_code_str"] = random_code_str
    ‘‘‘
    1 生成随机字符串
    2 响应set_cookie {"sessionid": "e21e12gg2d3sds"}
    3 在django_session表中插入一条记录
        session_key     session_data
    ‘‘‘

    return HttpResponse(data)

由于验证码需要生成图片,此处我们导入了PIL模块(用来生成图片的模块)

先生成一个image对象,图片的颜色应该是随机的,我们定义一个生成3个随机数字组成元组的函数

import random

    def get_random_color():
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

验证码中还需要有随机的字符串,此时我们从PIL模块中导入ImageDraw(画笔), ImageFont(字体)

首先生成一个字体对象,要先下载字体文件,并存放到项目中

然后通过该字体文件生成字体对象

font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)  # size为字体大小

然后往生成image图片中添加内容,内容应该为随机字符串,采用以下方法生成并添加到image图片中

draw = ImageDraw.Draw(image)  # 画笔
font = ImageFont.truetype("static/fonts/kumo.ttf", size=32)
temp = []
for i in range(5):
    random_char = random.choice(
        [chr(random.randint(65, 90)), chr(random.randint(97, 122)), str(random.randint(0, 9))])
    draw.text((i * 24, 20), random_char, get_random_color(), font=font)
    temp.append(random_char)

由于验证码图片只是发送给用户用来验证用的,没有必要保存到本地磁盘中,我们可以从io模块中导入BytesIO,在内存中生成空间来存放图片

from io import BytesIO
f = BytesIO()
image.save(f, "png")

data = f.getvalue()

此时将data返回给页面,用户就可以看到验证码图片了

但是为了方便我们接收到用户输入的验证码后进行验证,我们需要保存此次生成验证码的内容

# 保存随机字符串
random_code_str = "".join(temp)

现在我们需要考虑一个问题,用上面的方法保存验证码内容,如果一个用户先访问了登录页面,此时random_code_str被赋予了一个值,而这是另一个用户也访问了登录页面,这时random_code_str会被后一个值覆盖

那么前一个用户输入正确的验证码也无法验证成功了

在这种情况下,我们需要保证每一个用户都能保存住自己访问页面时验证码的值,可以考虑使用session

# 保存随机字符串
random_code_str = "".join(temp)
request.session["random_code_str"] = random_code_str

这里我们需要知道request.session做了什么:

1 生成随机字符串
2 响应set_cookie {"sessionid": "e21e12gg2d3sds"}
3 在django_session表中插入一条记录

如果用户访问时,已经有了cookie,那么这个操作会更新数据库django_session表中session_data的内容,而不会改变session_key等其它内容

点击更新验证码

当我们登录时,经常会遇到验证码看不清的情况,此时我们可以通过点击验证码图片进行刷新

这个功能可以通过前端JS实现

    // 验证码刷新
    $("img").click(function () {
        $(this)[0].src += "?"
    })

找到验证码图片的img标签,给他绑定一个点击事件,通过DOM对象的方法,在该图片的src后面加一个?号便可实现再次访问

后端验证

def log_in(request):
    response = {"is_login": False, "error_msg": ""}
    if request.method == "POST":
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")
        valid_code = request.POST.get("valid_code")
        code_str = request.session.get("random_code_str")
        if valid_code.upper() == code_str.upper():
            user = auth.authenticate(username=username, password=pwd)
            if user:
                response["is_login"] = True
                auth.login(request, user)  # 1 {"user_id": 1} 2 request.user=user
            else:
                response["error_msg"] = "用户名密码错误"
        else:
            response["error_msg"] = "验证码错误"
        return HttpResponse(json.dumps(response))
    return render(request, "login.html")

我们先校验验证码是否正确,在验证码正确的前提下再使用auth组件进行用户名和密码的验证

需要注意,当用户名密码也验证成功后,我们使用auth.login()方法写session,但由于此前访问验证码图片时已经在数据库中生成了session记录,该方法会先flush清除记录,再添加新的记录

所以这时我们会看到cookie中的sessionid的值变了,这里要和生成验证码时使用的request.session方法区分开来

原文地址:https://www.cnblogs.com/QQ279366/p/8424224.html

时间: 2024-10-26 12:04:59

博客园项目-登录(验证码,ajax提交数据,session和cookie)的相关文章

博客园加密登录--jsencrypt

博客园加密登录--jsencrypt 问题由来    前几天在做项目的时候,发现一般做登录的时候只是一个非常简单的`form`表单,但是这样肯定是不安全的!所以想去看看其他比较流行的网站是怎么实现的.说到安全,我第一个想到的就是去看支付宝,毕竟人家那么大的系统并且管理的是money啊! 结果,支付宝的登录确实复杂,chrome的F12竟然找不到.算了,看看我大博客园吧! 下面就是从博客园登录页面copy下来的js登录代码片段 博客园登录时采用的ajax发信http登录请求,就是采用jsencyp

博客园客户端(Universal App)开发随笔 -- 数据基础准备

在开始之前,我们先了解下博客园提供的接口: 博客: http://wcf.open.cnblogs.com/blog/help新闻: http://wcf.open.cnblogs.com/news/help 以博客园_48小时阅读排行为例,返回的Xml如下图(RSS,如果你用IE打开的话,会提示你订阅..). 博客园的大部分API返回的都是RSS(还提供分页!),如果只是做一个简单的RSS reader,可以直接用SyndicationClient,在RetrieveFeedAsync后会把X

在Python中用Request库模拟登录(二):博客园(简单加密,无验证码)

源代码分析 博客园的登录页面非常简单,查看网页源代码,可以发现两个输入框的id分别为input1.input2,复选框的id为remember_me,登录按钮的id为signin. 还有一段JavaScript代码,下面来简单分析一下. 先来看$(function(){});函数: 1 $(function () { 2 $('#signin').bind('click', function () { 3 signin_go(); 4 }).val('登 录'); 5 }); $(functio

python爬虫:两种方法模拟登录博客园

第一方法用第三方库(requests):参考http://www.mamicode.com/info-detail-1839685.html 源代码分析 博客园的登录页面非常简单,查看网页源代码,可以发现两个输入框的id分别为input1.input2,复选框的id为remember_me,登录按钮的id为signin. 还有一段JavaScript代码,下面来简单分析一下. 先来看$(function(){});函数: 1 $(function () { 2 $('#signin').bind

使用python selenium-webdriver模拟博客园登录

初学python,最近在抱着虫师的python+selenium自动化的书看,也尝试写个登录功能的验证2333 code:########################## #使用python selenium-webdriver #模拟博客园的登录流程 #首页--登录页面--跳转回首页--检查--退出登录恢复环境 ########################### from selenium import webdriver import time import sys url_cnbl

博客园客户端(Universal App)开发随笔 – App也需要物流前的打包

想起来一个笑话:唐僧一行千辛万苦来到佛祖面前,准备取经,佛祖轻声问了一句:汝等带U盘了吗?师徒4人立刻昏倒在地.好吧,扯远了,不过是想告诉大家准备工作一定要到位. Universal App 的打包发布其实与传统的 Windows Phone / Windows Store App 项目并无太大不同,但是鉴于总有人会在这些步骤中遇到问题,而且即使是发布过几个应用的开发者也不例外,所以对这个看起来比较繁琐的过程做一个小结还是必要的. 打包前的准备工作 1. 修改编译模式 在调试程序时,我们通常会选

Xamarin Android 打造属于自己的博客园APP(2)

好尴尬,隔了四个月才写第二篇幅,自己都不好意思了.这个拖延症好尴尬,妈蛋! 为那些在期待续集的同学说声sorry! 下面开始正文: 完成功能: 1.分页获取首页文章 2.分页获取精华文章 3.分页获取新闻 4.分页获取知识库文章 5.博客园账号登录,获取收藏文章,我的博客 6.文章评论 在写第一篇的时候,那个时候APP接口是调用的博客园公开的wcf接口,很多功能都有所限制,有诸多的不方便.我看见官方有ios版本的博客园,我用fiddler监听了下请求地址,发现域名是以api.cnblogs.co

博客园的模拟登陆(Simulated Login)

查看正常情况下登录博客园时本地浏览器向博客园的服务器发送的数据 依据上一步得到的由本地浏览器发送给博客园服务器的数据包内容进行模拟登陆 scrapy模拟登陆博客园 Reference 1.查看正常情况下登录博客园时本地浏览器向博客园的服务器发送的数据 首先打开博客园登录界面,填入登录用户名和密码,按快捷键 Ctrl+Alt+I 打开开发者管理器,然后点击登录 按钮,则可以在开发者管理器里看到发送的数据包内容. 数据包内容的查看位置如下图所示. 下面贴出了该数据包的内容 1. General 1.

Scrapy爬博客园

D:进入D盘 scrapy startproject cnblogs创建博客园项目 cd cnblogs进入项目根目录 scrapy genspider blog www.cnblogs.com创建爬虫文件 blog.py: # -*- coding: utf-8 -*-import scrapy class BlogSpider(scrapy.Spider): name = 'blog' allowed_domains = ['www.cnblogs.com'] start_urls = ['