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

一,环境部署

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>

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

(0)

相关推荐

  • Django 生成登陆验证码代码分享

    环境准备 python3.52 pycharm5.05 Pillow 自制的验证码工具包/utils/check_code 验证码的作用 防恶意破解密码:防止,使用程序或机器人恶意去试密码.为了提高用户的体验,用户输入错误以后,才会要求输入验证码. 防论坛灌水:这个是很常见的.有一种程序叫做顶帖机,如果无限制的刷,整个论坛可能到处是拉圾信息,比如,百度贴吧,你只要是新用户或者刚刚关注的贴吧,要是发帖,会马上出现验证码. 有效防止注册,以防,使用程序或机器人去无限制注册账号. 防刷票,网上有很多投

  • Python 中Django验证码功能的实现代码

    为了防止机器人频繁登陆网站或者破坏分子恶意登陆,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart"(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序.可以防止恶意破解密码.刷票.论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试. 图形验证

  • Django自定义插件实现网站登录验证码功能

    前言 网站登录的时候我们常常会看到随机的验证码需要输入后台验证,如图: 现在我们来实现在Django中通过自定制插件来实现随机验证 check_code.py 基于PIL生成一个带验证码的图片和验证码,生成验证码图片需要Monaco.ttf字体(重要),可按自己要求更改check_code中的字体和字体文件位置 #!/usr/bin/env python # -*- coding:utf-8 -*- import random from PIL import Image, ImageDraw,

  • Django验证码的生成与使用示例

    前言 本文主要介绍的是关于Django验证码生成与使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 方法如下: 1.基于PIL生成一个带验证码的图片和验证码,生成验证码图片需要Monaco.ttf字体,可按自己要求更改check_code中的字体和字体文件位置,如下图 #!/usr/bin/env python # -*- coding:utf-8 -*- import random from PIL import Image, ImageDraw, ImageFont, Im

  • django 发送手机验证码的示例代码

    一.流程分析: 1.用户在项目前端,输入手机号,然后点击[获取验证码],将手机号发到post到后台. 2.后台验证手机号是否合法,是否已被占用,如果通过验证,则生成验证码,并通过运行脚本,让短信运营商向该手机号,发送该验证码,如果没通过验证,则返回错误信息 3.用户收到短信验证码以后,再次将所有信息post到后台. 4.后台验证各个数据,通过验证则完成实名制认证,如果没通过则返回错误信息. 总结,一次实名验证,需要两次ajax+post 二.对接短信商: 1.在云片网端: 1.注册云片网 地址:

  • Django为窗体加上防机器人的验证码功能过程解析

    这里我们使用 django-simple-captcha 模块,官方介绍如下:https://github.com/mbi/django-simple-captcha 一键安装: pip install django-simple-captcha 在 setting.py 中把 'captcha' 加到 INSTALLED_APP 的区块中 INSTALLED_APPS = ( # ... 'captcha', # ... ) 由于此模块会到数据库建立自己的数据表,因此要先执行数据库的 migr

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

    一,环境部署 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 用户标识,若担心用户信息风险,可作预处理(如哈

  • 使用puppeteer破解极验的滑动验证码

    基本的流程: 1. 打开前端网,点击登录. 2. 填写账号,密码. 3. 点解验证按钮,通过滑动验证,最后成功登陆. 代码实现: github上可以checkout. 具体代码如下所示: run.js const puppeteer = require('puppeteer'); const devices = require('puppeteer/DeviceDescriptors'); const iPhone = devices['iPhone 6 Plus']; let timeout

  • 基于python实现破解滑动验证码过程解析

    前言: 很多小伙伴们反馈,在web自动化的过程中,经常会被登录的验证码给卡住,不知道如何去通过验证码的验证.今天专门给大家来聊聊验证码的问题,一般的情况下遇到验证码我们可以都可以找开发去帮忙解决,关闭验证码,或者给一个万能的验证码!那么如果开发不提供帮助的话,我们自己有没有办法来处理这些验证码的问题呢?答案当然是有的,常见的验证码一般分为两类,一类是图文验证码,一类是滑动验证码! 今天我们主要来聊聊滑动验证码如何去识别破解. 滑动验证破解思路 关于滑动验证码破解的思路大体上来讲就是以下两个步骤:

  • Django中使用CORS实现跨域请求过程解析

    跨域请求: 请求url包含协议.网址.端口,任何一种不同都是跨域请求. 1.安装cors模块 pip install django-cors-headers 2.添加应用 INSTALLED_APPS = ( ... 'corsheaders', ... ) 3.设置中间件 MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] 4.添加允许访问的白名单,凡是出现在白名单的域名都可以访问后端接口 # CORS CORS_ORIG

  • vue中使用极验验证码的方法(附demo)

    前言: vue中使用极验验证码,最好是在页面渲染的时候(mounted)进行验证码的初始化,然后在初始化回调中绑定触发弹出验证码的事件.这样在点击按钮或者进行特定操作时能够快速的弹出验证码. 关键代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-widt

  • 在AspNetCore中使用极验做行为认证的验证流程

    极验验证 极验验证是一种在计算机领域用于区分自然人和机器人的,通过简单集成的方式,为开发者提供安全.便捷的云端验证服务. 与以往传统验证码不同的是,极验通过分析用户完成拼图过程中的行为特征,通过数据分析来判断是人还是机器.用户不必面对眼花缭乱的英文字符或汉字,整个验证过程变的像游戏一样有趣. 先上效果图 极验的流程 极验官方文档地址 https://docs.geetest.com/install/deploy/server/csharp 简单说明一下极验的验证流程 引用官方的图片 •向服务器发

  • Java开发中解决Js的跨域问题过程解析

    这篇文章主要介绍了Java开发中解决Js的跨域问题过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 主流方法有JSONP和CORS两种,这里记一下后者的方式,理论基础就是在请求的时候在http请求头中添加如下属性: //指定允许其他域名访问 Access-Control-Allow-Origin:http://localhost:8989 如果后端用Java开发,在返回请求中可以添加如下属性 1.在跨域问题中,如果不操作cookie,只需

  • 在 React Native 中给第三方库打补丁的过程解析

    目录 安装 使用 示例 有时使用了某个React Native 第三方库,可是它有些问题,我们不得不修改它的源码.本文介绍如何修改源码又不会意外丢失修改结果的方法. 我们可能不方便给原作者提 Pull Request,因为他们可能不愿意接受我们的更改.又或者原作者无法及时发布新版本. 种种原因,我们只有去修改 node_modules 目录下的文件. 可是当我们执行 yarn install 或 yarn add 时,原先的修改会丢失. 有没有办法让我们可以在 yarn install 或 ya

  • Python 200行代码实现一个滑动验证码过程详解

    前言 做网络爬虫的同学肯定见过各种各样的验证码,比较高级的有滑动.点选等样式,看起来好像挺复杂的,但实际上它们的核心原理还是还是很清晰的,本文章大致说明下这些验证码的原理以及带大家实现一个滑动验证码. 实际上这类验证码的校验是分为两个步骤的: 1.第一步就是前端的校验.一般来说,登录注册页面在点击提交的时候都会伴随着一个表单提交,在表单提交的时候会有 JavaScript 事件的触发.如果加入了验证码,那么在表单提交的时候会多加一个额外的验证,判断这个验证码是否已经成功完成了操作.如果没有的话,

  • Django 导出项目依赖库到 requirements.txt过程解析

    虚拟环境: 使用 pip freeze pip freeze > requirements.txt # 这种方式推荐配合 virtualenv ,否则会把整个环境中的包都列出来. 只扫描项目目录 使用 pipreqs 这个工具的好处是可以通过对项目目录的扫描,自动发现使用了那些类库,自动生成依赖清单.缺点是可能会有些偏差,需要检查并自己调整下. # 首先安装 pipreqs# pip install pipreqs # 安装位置在pip所在的目录下 # 使用方式也比较简单 pipreqs /va

随机推荐