python

超轻量级php框架startmvc

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

更新时间:2020-07-20 07:30:01 作者:startmvc
一,环境部署1.创建一个django测试项目二,文档部署1.下载安装python对应的SDK使用命令从Githu

一,环境部署

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 滑动验证码