Django中使用极验Geetest滑动验证码过程解析


Posted in Python onJuly 31, 2019

一,环境部署

1.创建一个django测试项目

二,文档部署

1.下载安装python对应的SDK

使用命令从Github导入完整项目:git clone https://github.com/GeeTeam/gt3-python-sdk.git

手动下载压缩包文件:https://github.com/GeeTeam/gt3-python-sdk/archive/master.zip

2.参数配置

修改请求参数(可选)

名称 说明
user_id 用户标识,若担心用户信息风险,可作预处理(如哈希处理)再提供
client_type 客户端类型,web(pc浏览器),h5(手机浏览器,包括webview),native(原生app),unknown(未知)
ip_address 客户端请求您服务器的ip地址,unknow表示未知

三.代码实现 

SDK:utils>geetest.py

import sys
import random
import json
import requests
import time
from hashlib import md5
if sys.version_info >= (3,):
  xrange = range  

VERSION = "3.0.0"
class GeetestLib(object):
  FN_CHALLENGE = "geetest_challenge"
  FN_VALIDATE = "geetest_validate"
  FN_SECCODE = "geetest_seccode"
  GT_STATUS_SESSION_KEY = "gt_server_status"
  API_URL = "http://api.geetest.com"
  REGISTER_HANDLER = "/register.php"
  VALIDATE_HANDLER = "/validate.php"
  JSON_FORMAT = False
  def __init__(self, captcha_id, private_key):
    self.private_key = private_key
    self.captcha_id = captcha_id
    self.sdk_version = VERSION
    self._response_str = ""
  def pre_process(self, user_id=None,new_captcha=1,JSON_FORMAT=1,client_type="web",ip_address=""):
    """
    验证初始化预处理.
    //TO DO arrage the parameter
    """
    status, challenge = self._register(user_id,new_captcha,JSON_FORMAT,client_type,ip_address)
    self._response_str = self._make_response_format(status, challenge,new_captcha)
    return status

  def _register(self, user_id=None,new_captcha=1,JSON_FORMAT=1,client_type="web",ip_address=""):
    pri_responce = self._register_challenge(user_id,new_captcha,JSON_FORMAT,client_type,ip_address)
    if pri_responce:
      if JSON_FORMAT == 1:
        response_dic = json.loads(pri_responce)
        challenge = response_dic["challenge"]
      else:
        challenge = pri_responce
    else:
      challenge=" "
    if len(challenge) == 32:
      challenge = self._md5_encode("".join([challenge, self.private_key]))
      return 1,challenge
    else:
      return 0, self._make_fail_challenge()

  def get_response_str(self):
    return self._response_str

  def _make_fail_challenge(self):
    rnd1 = random.randint(0, 99)
    rnd2 = random.randint(0, 99)
    md5_str1 = self._md5_encode(str(rnd1))
    md5_str2 = self._md5_encode(str(rnd2))
    challenge = md5_str1 + md5_str2[0:2]
    return challenge

  def _make_response_format(self, success=1, challenge=None,new_captcha=1):
    if not challenge:
      challenge = self._make_fail_challenge()
    if new_captcha:
      string_format = json.dumps(
        {'success': success, 'gt':self.captcha_id, 'challenge': challenge,"new_captcha":True})
    else:
      string_format = json.dumps(
        {'success': success, 'gt':self.captcha_id, 'challenge': challenge,"new_captcha":False})
    return string_format

  def _register_challenge(self, user_id=None,new_captcha=1,JSON_FORMAT=1,client_type="web",ip_address=""):
    if user_id:
      register_url = "{api_url}{handler}?gt={captcha_ID}&user_id={user_id}&json_format={JSON_FORMAT}&client_type={client_type}&ip_address={ip_address}".format(
          api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id,new_captcha=new_captcha,JSON_FORMAT=JSON_FORMAT,client_type=client_type,ip_address=ip_address)
    else:
      register_url = "{api_url}{handler}?gt={captcha_ID}&json_format={JSON_FORMAT}&client_type={client_type}&ip_address={ip_address}".format(
          api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id,new_captcha=new_captcha,JSON_FORMAT=JSON_FORMAT,client_type=client_type,ip_address=ip_address)
    try:
      response = requests.get(register_url, timeout=2)
      if response.status_code == requests.codes.ok:
        res_string = response.text
      else:
        res_string = ""
    except:
      res_string = ""
    return res_string

  def success_validate(self, challenge, validate, seccode, user_id=None,gt=None,data='',userinfo='',JSON_FORMAT=1):
    """
    正常模式的二次验证方式.向geetest server 请求验证结果.
    """
    if not self._check_para(challenge, validate, seccode):
      return 0
    if not self._check_result(challenge, validate):
      return 0
    validate_url = "{api_url}{handler}".format(
      api_url=self.API_URL, handler=self.VALIDATE_HANDLER)
    query = {
      "seccode": seccode,
      "sdk": ''.join( ["python_",self.sdk_version]),
      "user_id": user_id,
      "data":data,
      "timestamp":time.time(),
      "challenge":challenge,
      "userinfo":userinfo,
      "captchaid":gt,
      "json_format":JSON_FORMAT
    }
    backinfo = self._post_values(validate_url, query)
    if JSON_FORMAT == 1:
      backinfo = json.loads(backinfo)
      backinfo = backinfo["seccode"]
    if backinfo == self._md5_encode(seccode):
      return 1
    else:
      return 0

  def _post_values(self, apiserver, data):
    response = requests.post(apiserver, data)
    return response.text

  def _check_result(self, origin, validate):
    encodeStr = self._md5_encode(self.private_key + "geetest" + origin)
    if validate == encodeStr:
      return True
    else:
      return False

  def failback_validate(self, challenge, validate, seccode):
    """
    failback模式的二次验证方式.在本地对轨迹进行简单的判断返回验证结果.
    """
    if not self._check_para(challenge, validate, seccode):
      return 0
    validate_result = self._failback_check_result(
      challenge, validate,)
    return validate_result

  def _failback_check_result(self,challenge,validate):
    encodeStr = self._md5_encode(challenge)
    if validate == encodeStr:
      return True
    else:
      return False
  def _check_para(self, challenge, validate, seccode):
    return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip()))
  def _md5_encode(self, values):
    if type(values) == str:
      values = values.encode()
    m = md5(values)
    return m.hexdigest()

view.py

# _*_ coding=utf-8 _*_
import uuid, json
from rest_framework.views import APIView
from rest_framework.response import Response
from api.models import Account, UserToken
from django_redis import get_redis_connection
from django.http import HttpResponse
from api.utils.geetest import GeetestLib
# id和key需要在Geetest官网自行申请,示例id不可用
pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"
REDIS_CONN = get_redis_connection('default')
class GeetestView(APIView):

  def get(self, request):
    user_id = 'test'
    gt = GeetestLib(pc_geetest_id, pc_geetest_key)
    status = gt.pre_process(user_id)
    # 使用session
    # request.session[gt.GT_STATUS_SESSION_KEY] = status
    # request.session["user_id"] = user_id
    # 使用redis
    REDIS_CONN.set(gt.GT_STATUS_SESSION_KEY, status)
    REDIS_CONN.set("gt_user_id", user_id)
    response_str = gt.get_response_str()
    return HttpResponse(response_str)

  def post(self, request):
    # print(request.session.get("user_id"))
    print(request.META.get("HTTP_AUTHENTICATION"))
    print(request.data)
    gt = GeetestLib(pc_geetest_id, pc_geetest_key)
    challenge = request.data.get(gt.FN_CHALLENGE, '')
    validate = request.data.get(gt.FN_VALIDATE, '')
    seccode = request.data.get(gt.FN_SECCODE, '')
    # 验证username,pwd
    # status = request.session.get(gt.GT_STATUS_SESSION_KEY)
    # print(status)
    # user_id = request.session.get("user_id")
    # print(user_id)
    status = REDIS_CONN.get(gt.GT_STATUS_SESSION_KEY)
    user_id = REDIS_CONN.get("gt_user_id")
    if status:
      result = gt.success_validate(challenge, validate, seccode, user_id)
    else:
      result = gt.failback_validate(challenge, validate, seccode)
    result = {"status": "success"} if result else {"status": "fail"}
    # if result:
    #   # 证明验证码通过
    #   # 判断用户名和密码
    # else:
    #   # 返回验证码错误
    return HttpResponse(json.dumps(result))

url.py

path('pc-geetest/register', GeetestView.as_view()),
path('pc-geetest/ajax_validate', GeetestView.as_view()),

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">
  <title>Title</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="http://static.geetest.com/static/tools/gt.js"></script>
  <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
  <style>
    body {
      margin: 50px 0;
      text-align: center;
    }

    .inp {
      border: 1px solid gray;
      padding: 0 10px;
      width: 200px;
      height: 30px;
      font-size: 18px;
    }

    .btn {
      border: 1px solid gray;
      width: 100px;
      height: 30px;
      font-size: 18px;
      cursor: pointer;
    }

    #embed-captcha {
      width: 300px;
      margin: 0 auto;
    }

    .show {
      display: block;
    }

    .hide {
      display: none;
    }

    #notice {
      color: red;
    }

    /* 以下遮罩层为demo.用户可自行设计实现 */
    #mask {
      display: none;
      position: fixed;
      text-align: center;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      overflow: auto;
    }

    /* 可自行设计实现captcha的位置大小 */
    .popup-mobile {
      position: relative;
    }

    #popup-captcha-mobile {
      position: fixed;
      display: none;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      -webkit-transform: translate(-50%, -50%);
      z-index: 9999;
    }
  </style>


</head>
<body>
<div id="app">
  <div class="popup">
    <h2>弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值</h2>
    <br>
    <p>
      <label>用户名:</label>
      <input id="username1" class="inp" type="text" value="极验验证" v-model="username">
    </p>
    <br>
    <p>
      <label>密    码:</label>
      <input id="password1" class="inp" type="password" value="123456" v-model="pwd">
    </p>

    <br>
    <input class="btn" id="popup-submit" type="submit" value="提交" ref="popup">

    <div id="popup-captcha"></div>
  </div>
</div>
<script>
  // Vue.prototype.$axios = axios;
  const app = new Vue({
    el: "#app",
    data: {
      username: "极验验证",
      pwd: "123456"
    },
    mounted() {
      let that = this;

      // 验证开始需要向网站主后台获取id,challenge,success(是否启用failback)
      axios.request({
        url: "http://127.0.0.1:8008/pc-geetest/register?t=" + (new Date()).getTime(), // 加随机数防止缓存
        method: "get",
      }).then(function (data) {
        console.log(data.data);
        // 使用initGeetest接口
        // 参数1:配置参数
        // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
        initGeetest({
          gt: data.data.gt,
          challenge: data.data.challenge,
          product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
          offline: !data.data.success, // 表示用户后台检测极验服务器是否宕机,一般不需要关注
          new_captcha: true
          // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
        }, function (captchaObj) {
          // 成功的回调
          console.log("进入成功的回调");
          captchaObj.onSuccess(function () {
            let validate = captchaObj.getValidate();
            console.log(122233333)
            axios.request({
              url: "http://127.0.0.1:8008/pc-geetest/ajax_validate", // 进行二次验证
              method: "post",
              data: {
                username: that.username,
                password: that.pwd,
                geetest_challenge: validate.geetest_challenge,
                geetest_validate: validate.geetest_validate,
                geetest_seccode: validate.geetest_seccode
              }
            }).then(function (data) {
              console.log(data.data);
              if (data && (data.data.status === "success")) {
                alert("登录成功")
              } else {
                alert("登录失败")
              }
            })
          });
          console.log(that.$refs.popup);
          that.$refs.popup.onclick = function () {
            captchaObj.show();
          };
          // 将验证码加到id为captcha的元素里
          captchaObj.appendTo("#popup-captcha");
          // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
        });
      })


    }

  })
</script>
</body>
</html>

Django中使用极验Geetest滑动验证码过程解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用基于Python的Tornado框架的HTTP客户端的教程
Apr 24 Python
Django的URLconf中使用缺省视图参数的方法
Jul 18 Python
Python3正则匹配re.split,re.finditer及re.findall函数用法详解
Jun 11 Python
Python 给定的经纬度标注在地图上的实现方法
Jul 05 Python
Python使用lambda表达式对字典排序操作示例
Jul 25 Python
python打开使用的方法
Sep 30 Python
matlab中二维插值函数interp2的使用详解
Apr 22 Python
django 数据库返回queryset实现封装为字典
May 19 Python
Python日志处理模块logging用法解析
May 19 Python
tensorflow转换ckpt为savermodel模型的实现
May 25 Python
解决pip install psycopg2出错问题
Jul 09 Python
Python绘制K线图之可视化神器pyecharts的使用
Mar 02 Python
Python对接六大主流数据库(只需三步)
Jul 31 #Python
Python爬虫 scrapy框架爬取某招聘网存入mongodb解析
Jul 31 #Python
python爬虫 模拟登录人人网过程解析
Jul 31 #Python
Python爬虫 bilibili视频弹幕提取过程详解
Jul 31 #Python
Django实现跨域的2种方法
Jul 31 #Python
Django CSRF跨站请求伪造防护过程解析
Jul 31 #Python
在VS2017中用C#调用python脚本的实现
Jul 31 #Python
You might like
汉字转化为拼音(php版)
2006/10/09 PHP
php中理解print EOT分界符和echo EOT的用法区别小结
2010/02/21 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
用js解决数字不能换行问题
2010/08/10 Javascript
基于jQuery的倒计时插件代码
2011/05/07 Javascript
jQuery scroll事件实现监控滚动条分页示例
2014/04/04 Javascript
JavaScript检查某个function是否是原生代码的方法
2014/08/20 Javascript
JS实现CheckBox复选框全选、不选或全不选功能
2020/07/28 Javascript
JS+HTML5手机开发之滚动和惯性缓动实现方法分析
2016/06/12 Javascript
JS中sort函数排序用法实例分析
2016/06/16 Javascript
js判断数组key是否存在(不用循环)的简单实例
2016/08/03 Javascript
vue.js实现用户评论、登录、注册、及修改信息功能
2020/05/30 Javascript
js实现把时间戳转换为yyyy-MM-dd hh:mm 格式(es6语法)
2017/12/28 Javascript
Javascript中prototype与__proto__的关系详解
2018/03/11 Javascript
p5.js入门教程之小球动画示例代码
2018/03/15 Javascript
vue子组件改变父组件传递的prop值通过sync实现数据双向绑定(DEMO)
2020/02/01 Javascript
微信小程序实现限制用户转发功能的实例代码
2020/02/22 Javascript
Vue 的双向绑定原理与用法揭秘
2020/05/06 Javascript
[47:03]完美世界DOTA2联赛PWL S3 Galaxy Racer vs Phoenix 第二场 12.10
2020/12/13 DOTA
Python内置的HTTP协议服务器SimpleHTTPServer使用指南
2016/03/30 Python
使用python和pygame绘制繁花曲线的方法
2018/02/24 Python
Django admin.py 在修改/添加表单界面显示额外字段的方法
2019/08/22 Python
django-crontab 定时执行任务方法的实现
2019/09/06 Python
python实现人机五子棋
2020/03/25 Python
Python中使用threading.Event协调线程的运行详解
2020/05/02 Python
Python中实现输入一个整数的案例
2020/05/03 Python
Python+OpenCV图像处理——图像二值化的实现
2020/10/24 Python
css3强大的动画效果animate使用说明及浏览器兼容介绍
2013/01/09 HTML / CSS
法国在线宠物店:zooplus.fr
2018/02/23 全球购物
Proenza Schouler官方网站:纽约女装和配饰品牌
2019/01/03 全球购物
应聘英语教师求职信
2014/04/24 职场文书
书法大赛策划方案
2014/06/04 职场文书
光学与应用专业毕业生求职信
2014/09/01 职场文书
刑事上诉状(无罪)
2015/05/23 职场文书
Matplotlib绘制混淆矩阵的实现
2021/05/27 Python
写一个Python脚本下载哔哩哔哩舞蹈区的所有视频
2021/05/31 Python