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>密&nbsp;&nbsp;&nbsp;&nbsp;码:</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滑动验证码

上一篇:golang常见错误


下一篇:关系型数据库工作原理-时间复杂度(翻译自Coding-Geek文章)