zoukankan      html  css  js  c++  java
  • WEB开发-动态验证码

    1.基于Python实现,用到了django后台处理,刷新验证码功能,其他语言大同小异


    2.登录界面

    login.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
    
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="">
    
        <title>DevOPS v1.0</title>
    
        <!-- Bootstrap Core CSS -->
        <link href="/static/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    
        <!-- MetisMenu CSS -->
        <link href="/static/vendor/metisMenu/metisMenu.min.css" rel="stylesheet">
    
        <!-- Custom CSS -->
        <link href="/static/dist/css/sb-admin-2.css" rel="stylesheet">
    
        <!-- Custom Fonts -->
        <link href="/static/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    
        <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
            <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->
    
    </head>
    
    <body>
    
    <div class="container">
        <div class="row">
            <div class="col-md-4 col-md-offset-4">
                <div class="login-panel panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Please Sign In</h3>
                    </div>
                    <div class="panel-body">
                        <form role="form" action="/index/login/" method="post">
                            <fieldset>
                                <div class="form-group">
                                    <input class="form-control" placeholder="Username" name="username" type="text"
                                           autofocus>
                                </div>
                                <div class="form-group">
                                    <input class="form-control" placeholder="Password" name="password" type="password"
                                           value="">
                                </div>
                                <div class="form-group">
                                    <input class="form-control" placeholder="验证码" name="yanzhengma" type="text" value="">
                                    {#                                    <span><img src={{ data }}></span>#}
                                    {#                                    <span>{{ data }}</span>#}
                                    <img src="/index/yanzhengma/" onclick="ChangeCode(this);"/>
                                    <div style="color: red;">{{ msg }}</div>
                                </div>
                                <div class="checkbox">
                                    <label>
                                        <input name="remember" type="checkbox" value="Remember Me">Remember Me
                                    </label>
                                </div>
                                <!-- Change this to a button or input when using this as a form -->
                                {#                                <a href="/login/" class="btn btn-lg btn-success btn-block">Login</a>#}
                                <input type="submit" class="btn btn-lg btn-success btn-block" name="Login"/>
                            </fieldset>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <!-- jQuery -->
    <script src="/static/vendor/jquery/jquery.min.js"></script>
    
    <!-- Bootstrap Core JavaScript -->
    <script src="/static/vendor/bootstrap/js/bootstrap.min.js"></script>
    
    <!-- Metis Menu Plugin JavaScript -->
    <script src="/static/vendor/metisMenu/metisMenu.min.js"></script>
    
    <!-- Custom Theme JavaScript -->
    <script src="/static/dist/js/sb-admin-2.js"></script>
    
    <script type="text/javascript">
        function ChangeCode(ths) {
            var src_re = $(ths).attr('src');
            $(ths).attr('src', src_re + '?');
        }
    </script>
    
    </body>
    
    </html>

    里面涉及到2个后端视图函数login和get_yanzhengma


     3.后端视图函数

    helper.py

    # -*- coding=utf-8 -*-
    import random
    
    
    # 随机字母:
    def rndChar():
        return chr(random.randint(65, 90)) + chr(random.randint(65, 90)) + chr(random.randint(65, 90)) + chr(random.randint(65, 90))

    Django的views.py

    # -*- coding=utf-8 -*-
    ##############################
    from django.shortcuts import render, HttpResponse, render_to_response,redirect
    from app import models
    from helper import rndChar
    from PIL import Image, ImageFont, ImageDraw
    import io
    
    # Create your views here.
    
    def index(request):
        # return HttpResponse('123456')
        return render_to_response('app/pages/index.html')
    
    def login(request):
        if request.method == 'POST':
            print request.POST
            username = request.POST.get('username',None)
            password = request.POST.get('password',None)
            yanzhengma = request.POST.get('yanzhengma',None)
            # print yanzhengma,request.session['yanzhengma']
            if yanzhengma.upper() != request.session['yanzhengma'].upper():
                return render_to_response('app/pages/login.html',{'msg':'验证码错误'})
            count = models.AdminInfo.objects.filter(username=username,password=password).count()
            if count > 0:
                request.session['is_login'] = {'user':username}
                return redirect('/index/')
                # return render_to_response('app/pages/index.html')
            else:
                return render_to_response('app/pages/login.html',{'msg':'账户密码错误'})
        else:
            # print stream.getvalue()
            # im.save("static/image/t.png")
            # request.session['yanzhengma'] = text
            return render_to_response('app/pages/login.html',{'msg':''})
    
    def yanzhengma(request):
         #text为产生的4位随机字符串
        text = rndChar() 
        # print text
        request.session['yanzhengma'] = text
        #图片处理程序,将文本做成图片
        im = Image.new("RGB", (130, 35), (255, 255, 255))
        dr = ImageDraw.Draw(im)
        font = ImageFont.truetype("arial", 24)
        # simsunb.ttf 这个从windows fonts copy一个过来
        dr.text((10, 5), text, font=font, fill="#000000")
        # im.show()
        #创建一个io对象
        stream = io.BytesIO()
        #将图片对象im保存到stream对象里
        im.save(stream, "png")
        #stream.getvalue()图片二级制内容,再通过HttpResponse封装,返回给前端页面
        return HttpResponse(stream.getvalue())

    4.效果图展示


     5.备注:

    (1)img标签的src属性,去这个/get_yanzhengma/去取图片

    (2)get_yanzhengma函数执行

    (3)通过random模块生成随机码,4个字母

    (4)通过PIL模块将随机数字转换为图片对象im

    (5)创建一个BytesIO对象,内存对象,可以存储二进制的东西

    (6)将图片对象保存到BytesIO对象中,此处在内存里

    #话说为什么要将图片对象保存到BytesIO对象中而不是直接写到硬盘里存为图片文件呢?因为这样就保证了在同一个时刻,不同用户访问到的验证码是不一样的,而且都是存储在内存中的。

    #如果写成验证码图片文件到硬盘里,有可能B页面显示的验证码是ABCD,但是B用户还没提交,A用户这会访问,刷新了验证码,把验证码变更为DCBA了,B页面里看到的还是ABCD,导致一直输不对验证码;无法保证2个用户的验证码图片冲突问题

    #后端验证码的随机值是存储在session中的,每次用户GET请求,服务器上生成随机验证码存储在session中,并给页面返回,如果用户提交的验证码和后端session中记录的一致通过,如果不一致,重新刷新验证码,用户重新进行提交

    (7)BytesIO对象的getvalue()方法返回二进制内容

    (8)django提供的HttpResponse封装二进制内容为识别的东西传递给前端

    (7)前端img标签正常显示图片

    (9)用户点击图片,js先获取到这个图片标签,取到当前的src属性值存为变量src_re,然后更改src的属性值为src_re + ?

    #为什么要加?呢是因为GET请求,每最后加一个?代表一个新的url,但是效果呢是和/index/yanzhengma/是一致的,每点一次,后面加一个?。/index/yanzhengma/?    /index/yanzhengma/??这个意思

    #如果每次只更改src的属性值为/index/yanzhengma/的话,不会进行request请求,会直接浏览器缓存读取。达不到刷新验证码的目的

    原创:做时间的朋友
  • 相关阅读:
    NIS server on centOS 7
    fabric-python-基于centos 7
    玩玩Jenkins
    身份认证技术性能对比
    Linux时区设置和时间同步-基于CentOS 6(最小安装)
    openldap+phpadmin的最简安装和配置
    tomcat8.5的网页管理(远程)配置、SSL证书配置-基于Debian 9
    tomcat添加为service服务-基于Debian 9
    安装、配置MySQL5.8基于Debian 9(用apt-get install 默认安装结果是mariadb)
    下载并配置jdk环境-基于debain 9
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/5914459.html
Copyright © 2011-2022 走看看