zoukankan      html  css  js  c++  java
  • Django中使用geetest验证

    一、geetest的使用方法

    首先需要在setting中配置好文件

    GEE_TEST = {
        "gee_test_access_id": "37ca5631edd1e882721808d35163b3ad",
        "gee_test_access_key": "7eb11ccf3e0953bdd060ed8b60b0c4f5",
        "verify_status": True,  # 是否启用滑动验证码验证组件(True表示启用)
        "not_verify": [
            "2ba6b08d53a4fd27057a32537e2d55ae",
        ],  # 不用验证的用户(存放着用户的uid)
    }

    配置好需要用的的文件后

    我们还需要用到验证文件

    geetest.py

    # !/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import sys
    import random
    import json
    import requests
    import time
    from hashlib import md5
    
    if sys.version_info >= (3,):
        xrange = range
    
    VERSION = "3.2.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"
    
        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):
            """
            验证初始化预处理.
            """
            status, challenge = self._register(user_id)
            self._response_str = self._make_response_format(status, challenge)
            return status
    
        def _register(self, user_id=None):
            challenge = self._register_challenge(user_id)
            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):
            if not challenge:
                challenge = self._make_fail_challenge()
            string_format = json.dumps(
                {'success': success, 'gt': self.captcha_id, 'challenge': challenge})
            return string_format
    
        def _register_challenge(self, user_id=None):
            if user_id:
                register_url = "{api_url}{handler}?gt={captcha_ID}&user_id={user_id}".format(
                    api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id)
            else:
                register_url = "{api_url}{handler}?gt={captcha_ID}".format(
                    api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id)
            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=''):
            """
            正常模式的二次验证方式.向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
            }
            backinfo = self._post_values(validate_url, query)
            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_str = validate.split('_')
            encode_ans = validate_str[0]
            encode_fbii = validate_str[1]
            encode_igi = validate_str[2]
            decode_ans = self._decode_response(challenge, encode_ans)
            decode_fbii = self._decode_response(challenge, encode_fbii)
            decode_igi = self._decode_response(challenge, encode_igi)
            validate_result = self._validate_fail_image(
                decode_ans, decode_fbii, decode_igi)
            return validate_result
    
        def _check_para(self, challenge, validate, seccode):
            return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip()))
    
        def _validate_fail_image(self, ans, full_bg_index, img_grp_index):
            thread = 3
            full_bg_name = str(self._md5_encode(str(full_bg_index)))[0:10]
            bg_name = str(self._md5_encode(str(img_grp_index)))[10:20]
            answer_decode = ""
            for i in range(0, 9):
                if i % 2 == 0:
                    answer_decode += full_bg_name[i]
                elif i % 2 == 1:
                    answer_decode += bg_name[i]
            x_decode = answer_decode[4:]
            x_int = int(x_decode, 16)
            result = x_int % 200
            if result < 40:
                result = 40
            if abs(ans - result) < thread:
                return 1
            else:
                return 0
    
        def _md5_encode(self, values):
            if type(values) == str:
                values = values.encode()
            m = md5(values)
            return m.hexdigest()
    
        def _decode_rand_base(self, challenge):
            str_base = challenge[32:]
            i = 0
            temp_array = []
            for i in xrange(len(str_base)):
                temp_char = str_base[i]
                temp_ascii = ord(temp_char)
                result = temp_ascii - 87 if temp_ascii > 57 else temp_ascii - 48
                temp_array.append(result)
            decode_res = temp_array[0] * 36 + temp_array[1]
            return decode_res
    
        def _decode_response(self, challenge, userresponse):
            if len(userresponse) > 100:
                return 0
            shuzi = (1, 2, 5, 10, 50)
            chongfu = set()
            key = {}
            count = 0
            for i in challenge:
                if i in chongfu:
                    continue
                else:
                    value = shuzi[count % 5]
                    chongfu.add(i)
                    count += 1
                    key.update({i: value})
            res = 0
            for i in userresponse:
                res += key.get(i, 0)
            res = res - self._decode_rand_base(challenge)
            return res

    然后后编写我们的验证视图函数

    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)
    
            return Response({"error_no": 0, "data": response_str})

     用来校验验证码的方法

    captcha_verify.py

    from django.conf import settings
    from api.utils.geetest import GeeTestLib
    def verify(verify_data, uid=None, extend_params=None):
        """第三方滑动验证码校验.
    
        选用第三方的验证组件, 根据参数进行校验
        根据布尔值辨别是否校验通过
    
        Parameters
        ----------
    
        verify_data : dict
            请求数据
    
        uid: string, default: None
            用户UID, 如果存在就免受滑动验证码的限制
    
        extend_params : dict
            预留的扩展参数
    
        Returns
        -------
        True OR False
        """
        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

    最后在登陆视图函数中加入判断即可完成

    导入方法文件

    from app01.utils.geetest import GeeTestLib
    from django.conf import settings
    from app01.utils.captcha_verify import verify

  • 相关阅读:
    ES6深入浅出-5 新版对象-1.如何创建对象
    ES6深入浅出-4 迭代器与生成器-5.科班 V.S. 培训
    ES6深入浅出-4 迭代器与生成器-4.总结
    ES6深入浅出-4 迭代器与生成器-3.生成器 & for...of
    ES6深入浅出-4 迭代器与生成器-2.Symbol 和迭代器
    Spring cloud微服务安全实战-3-2 第一个API及注入攻击防护
    Spring cloud微服务安全实战-3-1 API安全 常见的安全机制
    Spring Cloud微服务安全实战- 2-1 环境安装
    Spring cloud微服务安全实战_汇总
    ES6深入浅出-4 迭代器与生成器-1.字面量增强
  • 原文地址:https://www.cnblogs.com/qq631243523/p/10139281.html
Copyright © 2011-2022 走看看