zoukankan      html  css  js  c++  java
  • 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>
    View Code

     

  • 相关阅读:
    sublime主题推荐
    安装JDK设置环境变量
    寻找灵感
    算法刷题3 PAT 1003 我要通过! (20 point(s))
    Java JDBC连接Mysql学习整理
    算法Day2-恶搞算法(网传88万代码生成)java实现
    算法刷题1:自测-1 打印沙漏 (20 point(s))
    Java I/O stream输入输出初整理
    Java this关键字初理解
    MD5加密算法
  • 原文地址:https://www.cnblogs.com/zivli/p/10479327.html
Copyright © 2011-2022 走看看