zoukankan      html  css  js  c++  java
  • 于登录随机验证码的实现

    一、验证码相关知识

    Python生成随机验证码,需要使用PIL模块.

    安装:

    pip3 install pillow

    基本使用

    1. 创建图片

    from PIL import Image
    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
      
    # 在图片查看器中打开
    # img.show()
      
    # 保存在本地
    with open('code.png','wb') as f:
        img.save(f,format='png')

    2. 创建画笔,用于在图片上画任意内容

    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    3. 画点

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示坐标
    4 # 第二个参数:表示颜色
    5 draw.point([100, 100], fill="red")
    6 draw.point([300, 300], fill=(255, 255, 255))

    4. 画线

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示起始坐标和结束坐标
    4 # 第二个参数:表示颜色
    5 draw.line((100,100,100,300), fill='red')
    6 draw.line((100,100,300,100), fill=(255, 255, 255))

    5. 画圆

    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')
    # 第一个参数:表示起始坐标和结束坐标(圆要画在其中间)
    # 第二个参数:表示开始角度
    # 第三个参数:表示结束角度
    # 第四个参数:表示颜色
    draw.arc((100,100,300,300),0,90,fill="red")

    6. 写文本

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示起始坐标
    4 # 第二个参数:表示写入内容
    5 # 第三个参数:表示颜色
    6 draw.text([0,0],'python',"red")

    7. 特殊字体文字

     1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
     2 draw = ImageDraw.Draw(img, mode='RGB')
     3 # 第一个参数:表示字体文件路径
     4 # 第二个参数:表示字体大小
     5 font = ImageFont.truetype("kumo.ttf", 28)
     6 # 第一个参数:表示起始坐标
     7 # 第二个参数:表示写入内容
     8 # 第三个参数:表示颜色
     9 # 第四个参数:表示颜色
    10 draw.text([0, 0], 'python', "red", font=font)

    图片验证码

     1 import random
     2   
     3 def check_code(width=120, height=30, char_length=5, font_file='kumo.ttf', font_size=28):
     4     code = []
     5     img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
     6     draw = ImageDraw.Draw(img, mode='RGB')
     7   
     8     def rndChar():
     9         """
    10         生成随机字母  
    11         :return:
    12         """
    13         return chr(random.randint(65, 90))
    14   
    15     def rndColor():
    16         """
    17         生成随机颜色
    18         :return:
    19         """
    20         return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
    21   
    22     # 写文字
    23     font = ImageFont.truetype(font_file, font_size)
    24     for i in range(char_length):
    25         char = rndChar()
    26         code.append(char)
    27         h = random.randint(0, 4)
    28         draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
    29   
    30     # 写干扰点
    31     for i in range(40):
    32         draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    33   
    34     # 写干扰圆圈
    35     for i in range(40):
    36         draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    37         x = random.randint(0, width)
    38         y = random.randint(0, height)
    39         draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
    40   
    41     # 画干扰线
    42     for i in range(5):
    43         x1 = random.randint(0, width)
    44         y1 = random.randint(0, height)
    45         x2 = random.randint(0, width)
    46         y2 = random.randint(0, height)
    47   
    48         draw.line((x1, y1, x2, y2), fill=rndColor())
    49   
    50     img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    51     return img,''.join(code)
    52   
    53   
    54 if __name__ == '__main__':
    55     # 1. 直接打开
    56     # img,code = check_code()
    57     # img.show()
    58   
    59     # 2. 写入文件
    60     # img,code = check_code()
    61     # with open('code.png','wb') as f:
    62     #     img.save(f,format='png')
    63   
    64     # 3. 写入内存(Python3)
    65     # from io import BytesIO
    66     # stream = BytesIO()
    67     # img.save(stream, 'png')
    68     # stream.getvalue()
    69   
    70     # 4. 写入内存(Python2)
    71     # import StringIO
    72     # stream = StringIO.StringIO()
    73     # img.save(stream, 'png')
    74     # stream.getvalue()
    75   
    76     pass

    二、图片验证码应用

    四种实现方式,越来越趋于完美

    方式一:

     # 方式一:这样的方式吧路径写死了,只能是那一张图片
        import os
        path = os.path.join(settings.BASE_DIR,"static","image","3.jpg")  #路径拼接
        with open(path,"rb") as f:
            data = f.read()
        return HttpResponse(data)

    方式二:

    # 方式二:每次都显示不同的图片,利用pillow模块,安装一个pillow模块
        from PIL import Image
        img = Image.new(mode="RGB",size=(120,40),color="green") #首先自己创建一个图片,参数size=(120,40) 代表长和高
        f = open("validcode.png","wb")#然后把图片放在一个指定的位置
        img.save(f,"png")  #保存图片
        f.close()
        with open("validcode.png","rb") as f:
            data = f.read()
        return HttpResponse(data)

    方式三:

     # 方式三:
        # 方式二也不怎么好,因为每次都要创建一个保存图片的文件,我们可以不让吧图片保存到硬盘上,
        # 在内存中保存,完了自动清除,那么就引入了方式三:利用BytesIO模块
        from io import BytesIO
        from PIL import Image
        img = Image.new(mode="RGB",size=(120,40),color="blue")
        f = BytesIO()  #内存文件句柄
        img.save(f,"png")  #保存文件
        data = f.getvalue()#打开文件(相当于python中的f.read())
        return HttpResponse(data)

    方式四:

     # 方式四:1、添加画笔,也就是在图片上写上一些文字
        #         2、并且字体随机,背景颜色随机
        from io import BytesIO
        from PIL import Image,ImageDraw,ImageFont
        import random
        #随机创建图片
        img = Image.new(mode="RGB",size=(120,40),color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
        draw = ImageDraw.Draw(img,"RGB")
        # 画干扰线
        for i in range(5):
            x1 = random.randint(0, 120)
            y1 = random.randint(0, 40)
            x2 = random.randint(0, 120)
            y2 = random.randint(0, 40)
    
            draw.line((x1, y1, x2, y2), fill=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
    
        font = ImageFont.truetype("static/font/kumo.ttf",20)  #20表示20像素
    
        str_list = []  #吧每次生成的验证码保存起来
        # 随机生成五个字符
        for i in range(5):
            random_num = str(random.randint(0, 9))  # 随机数字
            random_lower = chr(random.randint(65, 90))  # 随机小写字母
            random_upper = chr(random.randint(97, 122))  # 随机大写字母
            random_char = random.choice([random_num, random_lower, random_upper])
            print(random_char,"random_char")
            str_list.append(random_char)
            # (5 + i * 24, 10)表示坐标,字体的位置
            draw.text((5+i*24,10),random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
        print(str_list,"str_list")
        f = BytesIO()#内存文件句柄
        img.save(f,"png")   #img是一个对象
        data = f.getvalue()  #读取数据并返回至HTML
        valid_str = "".join(str_list)
        print(valid_str,"valid_str")
        request.session["keep_valid_code"] = valid_str   #吧保存到列表的东西存放至session中
        return HttpResponse(data)

    三、滑动验证码应用

     我们可以借助插件来做

    1、打开插件,找到自己需要的验证码

    2、筛选有用的路径

    3、把对应的视图函数也拿过来,注意还需要一个geetest.py的文件

    具体实现

    1 #滑动验证码
    2     url(r'^pc-geetest/register', pcgetcaptcha, name='pcgetcaptcha'),
    3     url(r'^pc-geetest/ajax_validate', pcajax_validate, name='pcajax_validate'),
    urls
     1 # ================
     2 from app01.geetest import GeetestLib
     3 pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
     4 pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"
     5 mobile_geetest_id = "7c25da6fe21944cfe507d2f9876775a9"
     6 mobile_geetest_key = "f5883f4ee3bd4fa8caec67941de1b903"
     7 # 滑动验证码
     8 def pcgetcaptcha(request):
     9     user_id = 'test'
    10     gt = GeetestLib(pc_geetest_id, pc_geetest_key)
    11     status = gt.pre_process(user_id)
    12     request.session[gt.GT_STATUS_SESSION_KEY] = status
    13     request.session["user_id"] = user_id
    14     response_str = gt.get_response_str()
    15     return HttpResponse(response_str)
    16 # 滑动验证码
    17 def pcajax_validate(request):
    18 
    19     if request.method == "POST":
    20         # 验证的验证码
    21         ret = {"flag": False, "error_msg": None}
    22         gt = GeetestLib(pc_geetest_id, pc_geetest_key)
    23         challenge = request.POST.get(gt.FN_CHALLENGE, '')
    24         validate = request.POST.get(gt.FN_VALIDATE, '')
    25         seccode = request.POST.get(gt.FN_SECCODE, '')
    26         status = request.session[gt.GT_STATUS_SESSION_KEY]
    27         user_id = request.session["user_id"]
    28         print("status",status)
    29         if status:
    30             result = gt.success_validate(challenge, validate, seccode, user_id)
    31         else:
    32             result = gt.failback_validate(challenge, validate, seccode)
    33         if result:  #如果验证验证码正确,就验证用户名是否正确
    34             username = request.POST.get("username")
    35             password = request.POST.get("password")
    36 
    37            # 验证用户名和密码
    38             user = auth.authenticate(username=username, password=password)
    39             if user:
    40                 # 如果验证成功就让登录
    41                 ret["flag"] = True
    42                 auth.login(request, user)
    43             else:
    44                 ret["error_msg"] = "用户名和密码错误"
    45         else:
    46             ret["error_msg"] = "验证码错误"
    47         return HttpResponse(json.dumps(ret))
    48     else:
    49         return render(request, "login.html")
    views
      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
      6     <meta name="viewport" content="width=device-width">
      7     <title>Title</title>
      8     <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
      9     <link rel="stylesheet" href="/static/css/login.css">
     10     <script src="/static/jquery-3.2.1.min.js"></script>
     11    滑动验证码的时候导入
     12     <script src="http://static.geetest.com/static/tools/gt.js"></script>
     13     <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
     14     <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
     15 
     16 </head>
     17 <body>
     18 <div class="container">
     19     <div class="row">
     20         <div class="col-md-1=10">
     21             <form class="form-horizontal" id="form_data" action="/login/" method="post">
     22                 {% csrf_token %}
     23                 <div class="form-group">
     24                     <label for="username" class="col-sm-2 control-label">用户名</label>
     25                     <div class="col-sm-5">
     26                         <input type="text" class="form-control" id="username" placeholder="username" name="username">
     27                     </div>
     28                 </div>
     29                 <div class="form-group">
     30                     <label for="password" class="col-sm-2 control-label">密码</label>
     31                     <div class="col-sm-5">
     32                         <input type="password" class="form-control" id="password" placeholder="password" name="password">
     33                     </div>
     34                 </div>
     35                 <div class="form-group">
     36                     <div class="row">
     37                         <div class="col-md-6 col-md-offset-1">
     38 {#                            文字部分#}
     39                             <label for="vialdCode" class="col-sm-2 control-label">验证码</label>
     40                              <div class="col-sm-5">
     41                                 <input type="text" class="form-control vialdCode_text" id="vialdCode" placeholder="验证码" name="vialdCode">
     42                             </div>
     43 {#                            图片部分#}
     44                              <div class="col-md-5">
     45                             <img class="vialdCode_img" src="/get_vaildCode_img/" alt="" width="200px" height="100px">
     46 {#                                 <a href=""></a>     #}
     47                         </div>
     48                         </div>
     49 
     50                     </div>
     51                 </div>
     52                 <div class="form-group">
     53                     <div class="col-sm-offset-2 col-sm-10">
     54                         <div class="checkbox">
     55                             <label>
     56                                 <input type="checkbox"> 下次自动登录
     57                             </label>
     58                         </div>
     59                     </div>
     60                 </div>
     61                 <div class="form-group">
     62                     <div class="col-sm-offset-2 col-sm-10">
     63                         <p>
     64                             <button type="button" class="btn btn-success login" id="submit">登录</button>
     65                             <span class="error has-error"></span></p>
     66                         <p>
     67                             <button type="button" class="btn btn-primary register">注册</button>
     68                         </p>
     69                     </div>
     70                     <div id="popup-captcha"></div>
     71                 </div>
     72             </form>
     73         </div>
     74     </div>
     75 </div>
     76 {#滑动验证码#}
     77 <script>
     78     var handlerPopup = function (captchaObj) {
     79         $("#submit").click(function () {
     80             captchaObj.show();
     81         });
     82         //定时函数
     83          $(".login").click(function () {
     84              function foo() {
     85                  $(".error").html("")
     86              }
     87 
     88              // 成功的回调
     89              captchaObj.onSuccess(function () {
     90                  var validate = captchaObj.getValidate();
     91                  $.ajax({
     92                      url: "/pc-geetest/ajax_validate", // 进行二次验证
     93                      type: "post",
     94                      dataType: "json",
     95                      headers: {"X-CSRFToken": $.cookie('csrftoken')},
     96                      data: {
     97                          username: $('#username').val(),
     98                          password: $('#password').val(),
     99                          geetest_challenge: validate.geetest_challenge,
    100                          geetest_validate: validate.geetest_validate,
    101                          geetest_seccode: validate.geetest_seccode
    102                      },
    103                      success: function (data) {
    104                          console.log(data);
    105                          if (data["flag"]) {
    106 {#                             alert(location.search);#}
    107 {#                             alert(location.search.slice(6));#}
    108 {#                             方式一#}
    109 {#                             if (location.search.slice(6)) {#}
    110                                  {#                            如果用户没有登录点赞的时候,当用户后来又登录了,就直接让跳转到当前点赞的那个路径#}
    111 {#                                 location.href = location.search.slice(6)#}
    112 {#                             }#}
    113 {#                             else {#}
    114 {#                                 window.location.href = '/index/'#}
    115 {#                             }#}
    116 {#                             方式二:#}
    117                              alert($.cookie("next_path"));
    118                              if ($.cookie("next_path")){
    119                                  location.href = $.cookie("next_path")
    120                              }
    121                              else{
    122                                  location.href = "/index/"
    123                              }
    124                          }
    125                          else {
    126                              $(".error").html(data["error_msg"]);
    127                              setTimeout(foo, 3000)
    128                          }
    129                      }
    130                  });
    131              });
    132 
    133          });
    134              // 将验证码加到id为captcha的元素里
    135              captchaObj.appendTo("#popup-captcha");
    136              // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
    137          };
    138     // 验证开始需要向网站主后台获取id,challenge,success(是否启用failback)
    139     $.ajax({
    140         url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加随机数防止缓存
    141         type: "get",
    142         dataType: "json",
    143         success: function (data) {
    144             // 使用initGeetest接口
    145             // 参数1:配置参数
    146             // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
    147             initGeetest({
    148                 gt: data.gt,
    149                 challenge: data.challenge,
    150                 product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
    151                 offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
    152                 // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
    153             }, handlerPopup);
    154         }
    155     });
    156 </script>
    login.html
  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/morgana/p/8496499.html
Copyright © 2011-2022 走看看