```官方下载``` 1. geetest.py 官方文件 from shop.utils.geetest import GeetestLib 2. captcha.py 视图文件 from shop.views.captcha import CaptchaView 3. captcha_verify.py 验证文件
```urls.py文件``` from shop.views.captcha import CaptchaView urlpatterns = [ # jiyan验证 re_path('captcha_check/', CaptchaView.as_view()), ]
```settings.py文件``` GEE_TEST = { "gee_test_access_id": "37ca5631edd1e882721808d35163b3ad", "gee_test_access_key": "7eb11ccf3e0953bdd060ed8b60b0c4f5", "verify_status": True, # 是否启用滑动验证码验证组件(True表示启用) "not_verify": [ "2ba6b08d53a4fd27057a32537e2d55ae", ], # 不用验证的用户(存放着用户的uid) }
```captcha.py视图文件``` # Python Library import json # Third-party Library from rest_framework.views import APIView from rest_framework.response import Response # JiYan from shop.utils.geetest import GeetestLib from django.conf import settings class CaptchaView(APIView): def get(self, request): gt = GeetestLib(settings.GEE_TEST["gee_test_access_id"], settings.GEE_TEST["gee_test_access_key"]) gt.pre_process() # 设置 geetest session, 用于是否启用滑动验证码向 geetest 发起远程验证, 如果取不到的话只是对本地轨迹进行校验 # self.request.session[gt.GT_STATUS_SESSION_KEY] = status # request.session["user_id"] = user_id response_str = gt.get_response_str() response_str = json.loads(response_str) """ response_str结果如下: { "success": 1, "gt": "37ca5631edd1e882721808d35163b3ad", "challenge": "2df4904f10c0a3f07fc5b60a429d5ef5" } """ return Response({"error_no": 0, "data": response_str}) """ 构建前段需要的格式: { "error_no": 0, "data": { "success": 1, "gt": "37ca5631edd1e882721808d35163b3ad", "challenge": "2df4904f10c0a3f07fc5b60a429d5ef5" } } """
```captcha_verify.py视图文件``` # 这个文件是官网方法演变 from django.conf import settings from shop.utils.geetest import GeetestLib def verify(verify_data, uid=None, extend_params=None): captcha_config = settings.GEE_TEST if captcha_config.get("verify_status"): status = True if uid in captcha_config.get("not_verify"): return True gt = GeetestLib(captcha_config["gee_test_access_id"], captcha_config["gee_test_access_key"]) challenge = verify_data.get(gt.FN_CHALLENGE, '') validate = verify_data.get(gt.FN_VALIDATE, '') seccode = verify_data.get(gt.FN_SECCODE, '') # status = request.session.get(gt.GT_STATUS_SESSION_KEY, 1) # user_id = request.session.get("user_id") if status: result = gt.success_validate(challenge, validate, seccode, None) else: result = gt.failback_validate(challenge, validate, seccode) return True if result else False else: return True
```geetest.py视图文件``` # 这个文件不用自己写,官网下载就可以 # 下载地址:https://docs.geetest.com/install/deploy/server/python # Python Library import sys, random, json, requests, time # Third-party Library 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()