侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

框架(架构)  /  管理员 发布于 7年前   159

一,环境部署

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 sysimport randomimport jsonimport requestsimport timefrom hashlib import md5if 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, jsonfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom api.models import Account, UserTokenfrom django_redis import get_redis_connectionfrom django.http import HttpResponsefrom 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解决订单并发问题【推荐】
    下一条:
    Django文件存储 默认存储系统解析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Filament v3.1版本发布(0个评论)
    • docker + gitea搭建一个git服务器流程步骤(0个评论)
    • websocket的三种架构方式使用优缺点浅析(0个评论)
    • ubuntu20.4系统中宿主机安装nginx服务,docker容器中安装php8.2实现运行laravel10框架网站(0个评论)
    • phpstudy_pro(小皮面板)中安装最新php8.2.9版本流程步骤(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2018-05
    • 2020-02
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-11
    • 2021-03
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-08
    • 2023-08
    • 2023-10
    • 2023-12
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客