├── README.md
├── README.rst
└── demo
├── django_demo
├── app
│ ├── __init__.py
│ ├── __init__.pyc
│ └── views.py
├── db.sqlite3
├── django_demo
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ ├── urls.pyc
│ └── wsgi.py
├── geetest
│ ├── __init__.py
│ └── geetest.py
├── manage.py
├── requirements.txt
└── static
│ ├── gt.js
│ └── index.html
├── flask_demo
├── geetest
│ ├── __init__.py
│ └── geetest.py
├── requirements.txt
├── start.py
├── static
│ └── gt.js
└── templates
│ └── login.html
└── tornado_demo
├── geetest
├── __init__.py
└── geetest.py
├── requirements.txt
├── start.py
└── static
├── gt.js
└── login.html
/README.md:
--------------------------------------------------------------------------------
1 | # Gt3 Python SDK
2 |
3 | # 概述
4 |
5 | > 行为验证 Python SDK目前提供基于`Flask`、`Tornado`、`Django`框架的demo。
6 |
7 | ## 开发环境
8 |
9 | |条目||
10 | |----|------|
11 | |python环境 | python3,建议python3.5|
12 | |依赖库|Web框架库(如`django`、`tornado`)等
您可以使用`pip3 install -r requirements.txt` 一键安装所有依赖|
13 |
14 | ## 资源导航
15 |
16 | |条目||
17 | |-------------|--------------|
18 | |产品结构流程|[通讯流程](/install/overview/flowchart/#通讯流程)|
19 | |SDK项目地址|[gt3-python-sdk](http://github.com/GeeTeam/gt3-python-sdk)|
20 |
21 | # 安装 Python SDK
22 |
23 | ## 下载SDK
24 |
25 | > 使用命令从Github导入完整项目
26 |
27 | ```
28 | git clone https://github.com/GeeTeam/gt3-python-sdk.git
29 | ```
30 |
31 | > 手动下载压缩包文件
32 |
33 | 从[Github: gt3-python-sdk](https://github.com/GeeTeam/gt3-python-sdk/archive/master.zip)下载`.zip`文件
34 |
35 | ## 下载pip依赖
36 |
37 | > 各框架demo路径中有requirements.txt文件,使用pip3一键安装
38 |
39 | ```
40 | pip3 install -r requirements.txt
41 | ```
42 |
43 | ## 配置密钥,修改请求参数
44 |
45 | > 配置密钥
46 |
47 | 从[极验管理后台](https://account.geetest.com/login)获取您的公钥(id)和私钥(key), 并在代码中配置。配置文件路径如下:
48 | - Django:`/demo/django_demo/app/views.py`
49 | - Flask:`/demo/flask_demo/start.py`
50 | - Tornado:`/demo/tornado_demo/start.py`
51 |
52 | > 修改请求参数(可选)
53 |
54 | 名称|说明
55 | ----|------
56 | user_id|user_id作为终端用户的唯一标识,确定用户的唯一性;作用于提供进阶数据分析服务,可在api1 或 api2 接口传入,不传入也不影响验证服务的使用;若担心用户信息风险,可作预处理(如哈希处理)再提供到极验 ;
57 | client_type|客户端类型,**web**(pc浏览器),**h5**(手机浏览器,包括webview),**native**(原生app),**unknown**(未知)
58 | ip_address|客户端请求您服务器的ip地址,**unknow**表示未知
59 |
60 | # 运行 demo
61 |
62 | > 您也许需要使用`sudo`命令才能执行下列命令
63 |
64 | ### Flask demo 运行
65 |
66 | >命令行进入flask_demo文件夹路径,执行命令:
67 |
68 | ```
69 | $ python3 start.py
70 | ```
71 |
72 | 在浏览器中访问`http://localhost:5000`即可看到demo界面。
73 |
74 | ### Tornado demo运行
75 |
76 | > 命令行进入tornado_demo文件夹路径,执行命令:
77 |
78 | ```
79 | $ python3 start.py
80 | ```
81 |
82 | 在浏览器中访问`http://localhost:8088`即可看到demo界面
83 |
84 | ### Django demo运行
85 |
86 | > 命令行进入django_demo文件夹路径,执行命令:
87 |
88 | ```
89 | $ python3 manage.py runserver 0.0.0.0:8000
90 | ```
91 |
92 | 在浏览器中访问`http://localhost:8000`即可看到demo界面
93 |
94 |
95 | 发布日志
96 | -----------------
97 | + 3.4.0
98 |
99 | - 优化包结构
100 | - 整理代码失效链接
101 | - 升级新版failback表现形式
102 |
103 | + 3.3.2
104 |
105 | - 去掉代码和文档中的已失效的链接
106 |
107 | + 3.3.1
108 |
109 | - 保持 sdk 包名和导入名保持一致, geetest.
110 |
111 | + 3.3.0
112 |
113 | - 保持 sdk 包名和导入名保持一致, geetest.
114 |
115 | + 3.2.0
116 |
117 | - 添加用户标识(user_id)的接口
118 |
119 | + 3.1.2
120 |
121 | - 支持Python3
122 |
123 | + 3.1.1
124 |
125 | - 统一接口
126 |
127 | + 3.1.0
128 |
129 | - 添加challenge加密特性,使验证更安全, 老版本更新请先联系管理员
130 |
131 | + 3.0.1
132 |
133 | - 修复failback情况下 无法正确解码答案的错误
134 |
135 | + 3.0.0
136 |
137 | - 去除SDK对Session操作, 现在Session部分由开发者自己处理
138 | - 简易化初始化过程.
139 | - 修复failback模式BUG
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | Gt3 Python SDK
2 | ===============
3 |
4 | 极验验证的Python SDK目前提供基于django, flask, tornado框架的DEMO。
5 |
6 |
7 | 开发环境
8 | ----------------
9 |
10 | - Python (推荐3.5)
11 | - django, flask, tornado框架
12 |
13 | 快速开始
14 | ---------------
15 |
16 | 下面使用示例代码的均以flask框架为例。
17 |
18 | 1. 获取代码
19 |
20 | 从 `Github `__ 上Clone代码:
21 |
22 | .. code-block:: bash
23 |
24 | $ git clone https://github.com/GeeTeam/gt3-python-sdk.git
25 |
26 | 2. 安装pip依赖
27 |
28 | .. code-block:: bash
29 |
30 | $ sudo pip3 install -r requirements.txt
31 |
32 | 3. 初始化验证
33 |
34 |
35 | 在调用GeetestLib前请自行设定公钥和私钥,用户id为可选项,默认为随机数字:
36 |
37 | .. code-block :: python
38 |
39 | captach_id = "你的公钥"
40 | private_key = "你的私钥"
41 | user_id = random.randint(1,100)
42 |
43 | 根据自己的私钥初始化验证
44 |
45 | .. code-block :: python
46 |
47 | @app.route('/getcaptcha', methods=["GET"])
48 | def get_captcha():
49 | user_id = random.randint(1,100)
50 | gt = GeetestLib(captcha_id, private_key)
51 | status = gt.pre_process(user_id)
52 | session[gt.GT_STATUS_SESSION_KEY] = status
53 | session["user_id"] = user_id
54 | response_str = gt.get_response_str()
55 | return response_str
56 |
57 | 4. 二次验证
58 |
59 | .. code-block :: python
60 |
61 | @app.route('/validate', methods=["POST"])
62 | def validate_capthca():
63 | gt = GeetestLib(captcha_id, private_key)
64 | status = session[gt.GT_STATUS_SESSION_KEY]
65 | challenge = request.form[gt.FN_CHALLENGE]
66 | validate = request.form[gt.FN_VALIDATE]
67 | seccode = request.form[gt.FN_SECCODE]
68 | user_id = session["user_id"]
69 | if status:
70 | result = gt.success_validate(challenge, validate, seccode, user_id)
71 | else:
72 | result = gt.fail_validate(challenge, validate, seccode)
73 | result = "success" if result else "fail"
74 | return result
75 |
76 |
77 | 运行demo
78 | ---------------------
79 |
80 | 1. django demo运行:进入django_demo文件夹,运行:
81 |
82 | .. code-block:: bash
83 |
84 | $ python manage.py runserver 0.0.0.0:8000
85 |
86 | 在浏览器中访问http://localhost:8000即可看到Demo界面
87 |
88 | 2. flask demo运行:进入flask_demo文件夹,运行:
89 |
90 | .. code-block:: bash
91 |
92 | $ python start.py
93 |
94 | 在浏览器中访问http://localhost:5000即可看到Demo界面
95 |
96 | 3. tornado demo运行:进入tornado_demo文件夹,运行:
97 |
98 | .. code-block:: bash
99 |
100 | $ python start.py
101 |
102 | 在浏览器中访问http://localhost:8088即可看到Demo界面
103 |
104 |
105 | 发布日志
106 | -----------------
107 | + 3.3.2
108 |
109 | - 去掉代码和文档中的已失效的链接
110 |
111 | + 3.3.1
112 |
113 | - 保持 sdk 包名和导入名保持一致, geetest.
114 |
115 | + 3.3.0
116 |
117 | - 保持 sdk 包名和导入名保持一致, geetest.
118 |
119 | + 3.2.0
120 |
121 | - 添加用户标识(user_id)的接口
122 |
123 | + 3.1.2
124 |
125 | - 支持Python3
126 |
127 | + 3.1.1
128 |
129 | - 统一接口
130 |
131 | + 3.1.0
132 |
133 | - 添加challenge加密特性,使验证更安全, 老版本更新请先联系管理员
134 |
135 | + 3.0.1
136 |
137 | - 修复failback情况下 无法正确解码答案的错误
138 |
139 | + 3.0.0
140 |
141 | - 去除SDK对Session操作, 现在Session部分由开发者自己处理
142 | - 简易化初始化过程.
143 | - 修复failback模式BUG
144 |
--------------------------------------------------------------------------------
/demo/django_demo/app/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/app/__init__.py
--------------------------------------------------------------------------------
/demo/django_demo/app/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/app/__init__.pyc
--------------------------------------------------------------------------------
/demo/django_demo/app/views.py:
--------------------------------------------------------------------------------
1 | import json
2 | from django.http import HttpResponse
3 | from django.shortcuts import render_to_response, RequestContext
4 |
5 | from geetest import GeetestLib
6 |
7 | # 请在官网申请ID使用,示例ID不可使用
8 | pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
9 | pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"
10 | mobile_geetest_id = "7c25da6fe21944cfe507d2f9876775a9"
11 | mobile_geetest_key = "f5883f4ee3bd4fa8caec67941de1b903"
12 |
13 |
14 | def home(request):
15 | return render_to_response("index.html", context_instance=RequestContext(request))
16 |
17 |
18 | def pcgetcaptcha(request):
19 | user_id = 'test'
20 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
21 | status = gt.pre_process(user_id)
22 | request.session[gt.GT_STATUS_SESSION_KEY] = status
23 | request.session["user_id"] = user_id
24 | response_str = gt.get_response_str()
25 | return HttpResponse(response_str)
26 |
27 |
28 | def mobilegetcaptcha(request):
29 | user_id = 'test'
30 | gt = GeetestLib(mobile_geetest_id, mobile_geetest_key)
31 | status = gt.pre_process(user_id)
32 | request.session[gt.GT_STATUS_SESSION_KEY] = status
33 | request.session["user_id"] = user_id
34 | response_str = gt.get_response_str()
35 | return HttpResponse(response_str)
36 |
37 |
38 | def pcvalidate(request):
39 | if request.method == "POST":
40 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
41 | challenge = request.POST.get(gt.FN_CHALLENGE, '')
42 | validate = request.POST.get(gt.FN_VALIDATE, '')
43 | seccode = request.POST.get(gt.FN_SECCODE, '')
44 | status = request.session[gt.GT_STATUS_SESSION_KEY]
45 | user_id = request.session["user_id"]
46 | if status:
47 | result = gt.success_validate(challenge, validate, seccode, user_id)
48 | else:
49 | result = gt.failback_validate(challenge, validate, seccode)
50 | result = "登录成功
" if result else "登录失败
"
51 | return HttpResponse(result)
52 | return HttpResponse("error")
53 |
54 |
55 | def pcajax_validate(request):
56 | if request.method == "POST":
57 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
58 | challenge = request.POST.get(gt.FN_CHALLENGE, '')
59 | validate = request.POST.get(gt.FN_VALIDATE, '')
60 | seccode = request.POST.get(gt.FN_SECCODE, '')
61 | status = request.session[gt.GT_STATUS_SESSION_KEY]
62 | user_id = request.session["user_id"]
63 | if status:
64 | result = gt.success_validate(challenge, validate, seccode, user_id)
65 | else:
66 | result = gt.failback_validate(challenge, validate, seccode)
67 | result = {"status": "success"} if result else {"status": "fail"}
68 | return HttpResponse(json.dumps(result))
69 | return HttpResponse("error")
70 |
71 |
72 | def mobileajax_validate(request):
73 | if request.method == "POST":
74 | gt = GeetestLib(mobile_geetest_id, mobile_geetest_key)
75 | challenge = request.POST.get(gt.FN_CHALLENGE, '')
76 | validate = request.POST.get(gt.FN_VALIDATE, '')
77 | seccode = request.POST.get(gt.FN_SECCODE, '')
78 | status = request.session[gt.GT_STATUS_SESSION_KEY]
79 | user_id = request.session["user_id"]
80 | if status:
81 | result = gt.success_validate(challenge, validate, seccode, user_id)
82 | else:
83 | result = gt.failback_validate(challenge, validate, seccode)
84 | result = {"status": "success"} if result else {"status": "fail"}
85 | return HttpResponse(json.dumps(result))
86 | return HttpResponse("error")
87 |
--------------------------------------------------------------------------------
/demo/django_demo/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/db.sqlite3
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/django_demo/__init__.py
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/django_demo/__init__.pyc
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for django_demo project.
3 |
4 | For more information on this file, see
5 | https://docs.djangoproject.com/en/1.7/topics/settings/
6 |
7 | For the full list of settings and their values, see
8 | https://docs.djangoproject.com/en/1.7/ref/settings/
9 | """
10 |
11 | import os
12 |
13 | BASE_DIR = os.path.dirname(os.path.dirname(__file__))
14 |
15 | # SECURITY WARNING: keep the secret key used in production secret!
16 | SECRET_KEY = 'g-^epx6*uxh!mv6#fwdy9m(xi2-+a*3g2wi73fuevua$m00_3o'
17 |
18 | DEBUG = True
19 |
20 | TEMPLATE_DEBUG = True
21 |
22 | ALLOWED_HOSTS = []
23 |
24 | INSTALLED_APPS = (
25 | 'django.contrib.admin',
26 | 'django.contrib.auth',
27 | 'django.contrib.contenttypes',
28 | 'django.contrib.sessions',
29 | 'django.contrib.messages',
30 | 'django.contrib.staticfiles',
31 | 'app',
32 | )
33 |
34 | MIDDLEWARE_CLASSES = (
35 | 'django.contrib.sessions.middleware.SessionMiddleware',
36 | 'django.middleware.common.CommonMiddleware',
37 | # 'django.middleware.csrf.CsrfViewMiddleware',
38 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
39 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
40 | 'django.contrib.messages.middleware.MessageMiddleware',
41 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
42 | )
43 |
44 | ROOT_URLCONF = 'django_demo.urls'
45 |
46 | WSGI_APPLICATION = 'django_demo.wsgi.application'
47 |
48 | DATABASES = {
49 | 'default': {
50 | 'ENGINE': 'django.db.backends.sqlite3',
51 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
52 | }
53 | }
54 |
55 | LANGUAGE_CODE = 'en-us'
56 |
57 | TIME_ZONE = 'UTC'
58 |
59 | USE_I18N = True
60 |
61 | USE_L10N = True
62 |
63 | USE_TZ = True
64 |
65 | STATIC_URL = '/static/'
66 |
67 | TEMPLATE_DIRS = (
68 | "static",
69 | )
70 | STATICFILES_DIRS = [
71 | os.path.join(BASE_DIR, 'static')
72 | ]
73 |
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/settings.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/django_demo/settings.pyc
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | urlpatterns = [
4 | url(r'^pc-geetest/register', 'app.views.pcgetcaptcha', name='pcgetcaptcha'),
5 | url(r'^mobile-geetest/register', 'app.views.mobilegetcaptcha', name='mobilegetcaptcha'),
6 | url(r'^pc-geetest/validate$', 'app.views.pcvalidate', name='pcvalidate'),
7 | url(r'^pc-geetest/ajax_validate', 'app.views.pcajax_validate', name='pcajax_validate'),
8 | url(r'^mobile-geetest/ajax_validate', 'app.views.mobileajax_validate', name='mobileajax_validate'),
9 | url(r'/*', 'app.views.home', name='home'),
10 | ]
11 |
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/urls.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GeeTeam/gt3-python-sdk/afde6d6bdd15145e97579119495ca2cc82634963/demo/django_demo/django_demo/urls.pyc
--------------------------------------------------------------------------------
/demo/django_demo/django_demo/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for django_demo project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_demo.settings")
12 |
13 | from django.core.wsgi import get_wsgi_application
14 | application = get_wsgi_application()
15 |
--------------------------------------------------------------------------------
/demo/django_demo/geetest/__init__.py:
--------------------------------------------------------------------------------
1 | from .geetest import GeetestLib, VERSION
--------------------------------------------------------------------------------
/demo/django_demo/geetest/geetest.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import random
3 | import json
4 | import requests
5 | import time
6 | from hashlib import md5
7 |
8 | if sys.version_info >= (3,):
9 | xrange = range
10 |
11 | VERSION = "3.0.0"
12 |
13 |
14 | class GeetestLib(object):
15 | FN_CHALLENGE = "geetest_challenge"
16 | FN_VALIDATE = "geetest_validate"
17 | FN_SECCODE = "geetest_seccode"
18 |
19 | GT_STATUS_SESSION_KEY = "gt_server_status"
20 |
21 | API_URL = "http://api.geetest.com"
22 | REGISTER_HANDLER = "/register.php"
23 | VALIDATE_HANDLER = "/validate.php"
24 | JSON_FORMAT = False
25 |
26 | def __init__(self, captcha_id, private_key):
27 | self.private_key = private_key
28 | self.captcha_id = captcha_id
29 | self.sdk_version = VERSION
30 | self._response_str = ""
31 |
32 | def pre_process(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
33 | status, challenge = self._register(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
34 | self._response_str = self._make_response_format(status, challenge, new_captcha)
35 | return status
36 |
37 | def _register(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
38 | pri_responce = self._register_challenge(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
39 | if pri_responce:
40 | if JSON_FORMAT == 1:
41 | response_dic = json.loads(pri_responce)
42 | challenge = response_dic["challenge"]
43 | else:
44 | challenge = pri_responce
45 | else:
46 | challenge = " "
47 | if len(challenge) == 32:
48 | challenge = self._md5_encode("".join([challenge, self.private_key]))
49 | return 1, challenge
50 | else:
51 | return 0, self._make_fail_challenge()
52 |
53 | def get_response_str(self):
54 | return self._response_str
55 |
56 | def _make_fail_challenge(self):
57 | rnd1 = random.randint(0, 99)
58 | rnd2 = random.randint(0, 99)
59 | md5_str1 = self._md5_encode(str(rnd1))
60 | md5_str2 = self._md5_encode(str(rnd2))
61 | challenge = md5_str1 + md5_str2[0:2]
62 | return challenge
63 |
64 | def _make_response_format(self, success=1, challenge=None, new_captcha=1):
65 | if not challenge:
66 | challenge = self._make_fail_challenge()
67 | if new_captcha:
68 | string_format = json.dumps(
69 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": True})
70 | else:
71 | string_format = json.dumps(
72 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": False})
73 | return string_format
74 |
75 | def _register_challenge(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
76 | if user_id:
77 | 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(
78 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id,
79 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
80 | else:
81 | register_url = "{api_url}{handler}?gt={captcha_ID}&json_format={JSON_FORMAT}&client_type={client_type}&ip_address={ip_address}".format(
82 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id,
83 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
84 | try:
85 | response = requests.get(register_url, timeout=2)
86 | if response.status_code == requests.codes.ok:
87 | res_string = response.text
88 | else:
89 | res_string = ""
90 | except:
91 | res_string = ""
92 | return res_string
93 |
94 | def success_validate(self, challenge, validate, seccode, user_id=None, gt=None, data='', userinfo='',
95 | JSON_FORMAT=1):
96 | """
97 | 正常模式的二次验证方式.向geetest server 请求验证结果.
98 | """
99 | if not self._check_para(challenge, validate, seccode):
100 | return 0
101 | if not self._check_result(challenge, validate):
102 | return 0
103 | validate_url = "{api_url}{handler}".format(
104 | api_url=self.API_URL, handler=self.VALIDATE_HANDLER)
105 | query = {
106 | "seccode": seccode,
107 | "sdk": ''.join(["python_", self.sdk_version]),
108 | "user_id": user_id,
109 | "data": data,
110 | "timestamp": time.time(),
111 | "challenge": challenge,
112 | "userinfo": userinfo,
113 | "captchaid": gt,
114 | "json_format": JSON_FORMAT
115 | }
116 | backinfo = self._post_values(validate_url, query)
117 | if JSON_FORMAT == 1:
118 | backinfo = json.loads(backinfo)
119 | backinfo = backinfo["seccode"]
120 | if backinfo == self._md5_encode(seccode):
121 | return 1
122 | else:
123 | return 0
124 |
125 | def _post_values(self, apiserver, data):
126 | response = requests.post(apiserver, data)
127 | return response.text
128 |
129 | def _check_result(self, origin, validate):
130 | encodeStr = self._md5_encode(self.private_key + "geetest" + origin)
131 | if validate == encodeStr:
132 | return True
133 | else:
134 | return False
135 |
136 | def failback_validate(self, challenge, validate, seccode):
137 | """
138 | failback模式的二次验证方式.在本地对轨迹进行简单的判断返回验证结果.
139 | """
140 | if not self._check_para(challenge, validate, seccode):
141 | return 0
142 | validate_result = self._failback_check_result(
143 | challenge, validate, )
144 | return validate_result
145 |
146 | def _failback_check_result(self, challenge, validate):
147 | encodeStr = self._md5_encode(challenge)
148 | if validate == encodeStr:
149 | return True
150 | else:
151 | return False
152 |
153 | def _check_para(self, challenge, validate, seccode):
154 | return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip()))
155 |
156 | def _md5_encode(self, values):
157 | if type(values) == str:
158 | values = values.encode()
159 | m = md5(values)
160 | return m.hexdigest()
161 |
--------------------------------------------------------------------------------
/demo/django_demo/manage.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | if __name__ == "__main__":
5 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_demo.settings")
6 |
7 | from django.core.management import execute_from_command_line
8 |
9 | execute_from_command_line(sys.argv)
10 |
--------------------------------------------------------------------------------
/demo/django_demo/requirements.txt:
--------------------------------------------------------------------------------
1 | certifi==2017.7.27.1
2 | chardet==3.0.4
3 | Django==1.8
4 | idna==2.6
5 | pytz==2017.3
6 | requests==2.18.4
7 | urllib3==1.22
8 |
--------------------------------------------------------------------------------
/demo/django_demo/static/gt.js:
--------------------------------------------------------------------------------
1 | "v0.4.8 Geetest Inc.";
2 |
3 | (function (window) {
4 | "use strict";
5 | if (typeof window === 'undefined') {
6 | throw new Error('Geetest requires browser environment');
7 | }
8 |
9 | var document = window.document;
10 | var Math = window.Math;
11 | var head = document.getElementsByTagName("head")[0];
12 |
13 | function _Object(obj) {
14 | this._obj = obj;
15 | }
16 |
17 | _Object.prototype = {
18 | _each: function (process) {
19 | var _obj = this._obj;
20 | for (var k in _obj) {
21 | if (_obj.hasOwnProperty(k)) {
22 | process(k, _obj[k]);
23 | }
24 | }
25 | return this;
26 | }
27 | };
28 |
29 | function Config(config) {
30 | var self = this;
31 | new _Object(config)._each(function (key, value) {
32 | self[key] = value;
33 | });
34 | }
35 |
36 | Config.prototype = {
37 | api_server: 'api.geetest.com',
38 | protocol: 'http://',
39 | typePath: '/gettype.php',
40 | fallback_config: {
41 | slide: {
42 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
43 | type: 'slide',
44 | slide: '/static/js/geetest.0.0.0.js'
45 | },
46 | fullpage: {
47 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
48 | type: 'fullpage',
49 | fullpage: '/static/js/fullpage.0.0.0.js'
50 | }
51 | },
52 | _get_fallback_config: function () {
53 | var self = this;
54 | if (isString(self.type)) {
55 | return self.fallback_config[self.type];
56 | } else if (self.new_captcha) {
57 | return self.fallback_config.fullpage;
58 | } else {
59 | return self.fallback_config.slide;
60 | }
61 | },
62 | _extend: function (obj) {
63 | var self = this;
64 | new _Object(obj)._each(function (key, value) {
65 | self[key] = value;
66 | })
67 | }
68 | };
69 | var isNumber = function (value) {
70 | return (typeof value === 'number');
71 | };
72 | var isString = function (value) {
73 | return (typeof value === 'string');
74 | };
75 | var isBoolean = function (value) {
76 | return (typeof value === 'boolean');
77 | };
78 | var isObject = function (value) {
79 | return (typeof value === 'object' && value !== null);
80 | };
81 | var isFunction = function (value) {
82 | return (typeof value === 'function');
83 | };
84 | var MOBILE = /Mobi/i.test(navigator.userAgent);
85 | var pt = MOBILE ? 3 : 0;
86 |
87 | var callbacks = {};
88 | var status = {};
89 |
90 | var nowDate = function () {
91 | var date = new Date();
92 | var year = date.getFullYear();
93 | var month = date.getMonth() + 1;
94 | var day = date.getDate();
95 | var hours = date.getHours();
96 | var minutes = date.getMinutes();
97 | var seconds = date.getSeconds();
98 |
99 | if (month >= 1 && month <= 9) {
100 | month = '0' + month;
101 | }
102 | if (day >= 0 && day <= 9) {
103 | day = '0' + day;
104 | }
105 | if (hours >= 0 && hours <= 9) {
106 | hours = '0' + hours;
107 | }
108 | if (minutes >= 0 && minutes <= 9) {
109 | minutes = '0' + minutes;
110 | }
111 | if (seconds >= 0 && seconds <= 9) {
112 | seconds = '0' + seconds;
113 | }
114 | var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds;
115 | return currentdate;
116 | }
117 |
118 | var random = function () {
119 | return parseInt(Math.random() * 10000) + (new Date()).valueOf();
120 | };
121 |
122 | var loadScript = function (url, cb) {
123 | var script = document.createElement("script");
124 | script.charset = "UTF-8";
125 | script.async = true;
126 |
127 | // 对geetest的静态资源添加 crossOrigin
128 | if ( /static\.geetest\.com/g.test(url)) {
129 | script.crossOrigin = "anonymous";
130 | }
131 |
132 | script.onerror = function () {
133 | cb(true);
134 | };
135 | var loaded = false;
136 | script.onload = script.onreadystatechange = function () {
137 | if (!loaded &&
138 | (!script.readyState ||
139 | "loaded" === script.readyState ||
140 | "complete" === script.readyState)) {
141 |
142 | loaded = true;
143 | setTimeout(function () {
144 | cb(false);
145 | }, 0);
146 | }
147 | };
148 | script.src = url;
149 | head.appendChild(script);
150 | };
151 |
152 | var normalizeDomain = function (domain) {
153 | // special domain: uems.sysu.edu.cn/jwxt/geetest/
154 | // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
155 | return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
156 | };
157 | var normalizePath = function (path) {
158 | path = path.replace(/\/+/g, '/');
159 | if (path.indexOf('/') !== 0) {
160 | path = '/' + path;
161 | }
162 | return path;
163 | };
164 | var normalizeQuery = function (query) {
165 | if (!query) {
166 | return '';
167 | }
168 | var q = '?';
169 | new _Object(query)._each(function (key, value) {
170 | if (isString(value) || isNumber(value) || isBoolean(value)) {
171 | q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
172 | }
173 | });
174 | if (q === '?') {
175 | q = '';
176 | }
177 | return q.replace(/&$/, '');
178 | };
179 | var makeURL = function (protocol, domain, path, query) {
180 | domain = normalizeDomain(domain);
181 |
182 | var url = normalizePath(path) + normalizeQuery(query);
183 | if (domain) {
184 | url = protocol + domain + url;
185 | }
186 |
187 | return url;
188 | };
189 |
190 | var load = function (config, send, protocol, domains, path, query, cb) {
191 | var tryRequest = function (at) {
192 |
193 | var url = makeURL(protocol, domains[at], path, query);
194 | loadScript(url, function (err) {
195 | if (err) {
196 | if (at >= domains.length - 1) {
197 | cb(true);
198 | // report gettype error
199 | if (send) {
200 | config.error_code = 508;
201 | var url = protocol + domains[at] + path;
202 | reportError(config, url);
203 | }
204 | } else {
205 | tryRequest(at + 1);
206 | }
207 | } else {
208 | cb(false);
209 | }
210 | });
211 | };
212 | tryRequest(0);
213 | };
214 |
215 |
216 | var jsonp = function (domains, path, config, callback) {
217 | if (isObject(config.getLib)) {
218 | config._extend(config.getLib);
219 | callback(config);
220 | return;
221 | }
222 | if (config.offline) {
223 | callback(config._get_fallback_config());
224 | return;
225 | }
226 |
227 | var cb = "geetest_" + random();
228 | window[cb] = function (data) {
229 | if (data.status == 'success') {
230 | callback(data.data);
231 | } else if (!data.status) {
232 | callback(data);
233 | } else {
234 | callback(config._get_fallback_config());
235 | }
236 | window[cb] = undefined;
237 | try {
238 | delete window[cb];
239 | } catch (e) {
240 | }
241 | };
242 | load(config, true, config.protocol, domains, path, {
243 | gt: config.gt,
244 | callback: cb
245 | }, function (err) {
246 | if (err) {
247 | callback(config._get_fallback_config());
248 | }
249 | });
250 | };
251 |
252 | var reportError = function (config, url) {
253 | load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
254 | time: nowDate(),
255 | captcha_id: config.gt,
256 | challenge: config.challenge,
257 | pt: pt,
258 | exception_url: url,
259 | error_code: config.error_code
260 | }, function (err) {})
261 | }
262 |
263 | var throwError = function (errorType, config) {
264 | var errors = {
265 | networkError: '网络错误',
266 | gtTypeError: 'gt字段不是字符串类型'
267 | };
268 | if (typeof config.onError === 'function') {
269 | config.onError(errors[errorType]);
270 | } else {
271 | throw new Error(errors[errorType]);
272 | }
273 | };
274 |
275 | var detect = function () {
276 | return window.Geetest || document.getElementById("gt_lib");
277 | };
278 |
279 | if (detect()) {
280 | status.slide = "loaded";
281 | }
282 |
283 | window.initGeetest = function (userConfig, callback) {
284 |
285 | var config = new Config(userConfig);
286 |
287 | if (userConfig.https) {
288 | config.protocol = 'https://';
289 | } else if (!userConfig.protocol) {
290 | config.protocol = window.location.protocol + '//';
291 | }
292 |
293 | // for KFC
294 | if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' ||
295 | userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') {
296 | config.apiserver = 'yumchina.geetest.com/'; // for old js
297 | config.api_server = 'yumchina.geetest.com';
298 | }
299 |
300 | if(userConfig.gt){
301 | window.GeeGT = userConfig.gt
302 | }
303 |
304 | if(userConfig.challenge){
305 | window.GeeChallenge = userConfig.challenge
306 | }
307 |
308 | if (isObject(userConfig.getType)) {
309 | config._extend(userConfig.getType);
310 | }
311 | jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) {
312 | var type = newConfig.type;
313 | var init = function () {
314 | config._extend(newConfig);
315 | callback(new window.Geetest(config));
316 | };
317 |
318 | callbacks[type] = callbacks[type] || [];
319 | var s = status[type] || 'init';
320 | if (s === 'init') {
321 | status[type] = 'loading';
322 |
323 | callbacks[type].push(init);
324 |
325 | load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
326 | if (err) {
327 | status[type] = 'fail';
328 | throwError('networkError', config);
329 | } else {
330 | status[type] = 'loaded';
331 | var cbs = callbacks[type];
332 | for (var i = 0, len = cbs.length; i < len; i = i + 1) {
333 | var cb = cbs[i];
334 | if (isFunction(cb)) {
335 | cb();
336 | }
337 | }
338 | callbacks[type] = [];
339 | }
340 | });
341 | } else if (s === "loaded") {
342 | init();
343 | } else if (s === "fail") {
344 | throwError('networkError', config);
345 | } else if (s === "loading") {
346 | callbacks[type].push(init);
347 | }
348 | });
349 |
350 | };
351 |
352 |
353 | })(window);
354 |
355 |
--------------------------------------------------------------------------------
/demo/django_demo/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | gt-python-django-demo
7 |
74 |
75 |
76 | 极验验证SDKDemo
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
108 |
109 |
158 |
159 |
160 |
161 |
181 |
182 |
219 |
220 |
221 |
222 |
239 |
240 |
294 |
295 |
296 |
297 |
--------------------------------------------------------------------------------
/demo/flask_demo/geetest/__init__.py:
--------------------------------------------------------------------------------
1 | from .geetest import GeetestLib, VERSION
--------------------------------------------------------------------------------
/demo/flask_demo/geetest/geetest.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import random
3 | import json
4 | import requests
5 | import time
6 | from hashlib import md5
7 |
8 | if sys.version_info >= (3,):
9 | xrange = range
10 |
11 | VERSION = "3.0.0"
12 |
13 |
14 | class GeetestLib(object):
15 | FN_CHALLENGE = "geetest_challenge"
16 | FN_VALIDATE = "geetest_validate"
17 | FN_SECCODE = "geetest_seccode"
18 |
19 | GT_STATUS_SESSION_KEY = "gt_server_status"
20 |
21 | API_URL = "http://api.geetest.com"
22 | REGISTER_HANDLER = "/register.php"
23 | VALIDATE_HANDLER = "/validate.php"
24 | JSON_FORMAT = False
25 |
26 | def __init__(self, captcha_id, private_key):
27 | self.private_key = private_key
28 | self.captcha_id = captcha_id
29 | self.sdk_version = VERSION
30 | self._response_str = ""
31 |
32 | def pre_process(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
33 | status, challenge = self._register(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
34 | self._response_str = self._make_response_format(status, challenge, new_captcha)
35 | return status
36 |
37 | def _register(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
38 | pri_responce = self._register_challenge(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
39 | if pri_responce:
40 | if JSON_FORMAT == 1:
41 | response_dic = json.loads(pri_responce)
42 | challenge = response_dic["challenge"]
43 | else:
44 | challenge = pri_responce
45 | else:
46 | challenge = " "
47 | if len(challenge) == 32:
48 | challenge = self._md5_encode("".join([challenge, self.private_key]))
49 | return 1, challenge
50 | else:
51 | return 0, self._make_fail_challenge()
52 |
53 | def get_response_str(self):
54 | return self._response_str
55 |
56 | def _make_fail_challenge(self):
57 | rnd1 = random.randint(0, 99)
58 | rnd2 = random.randint(0, 99)
59 | md5_str1 = self._md5_encode(str(rnd1))
60 | md5_str2 = self._md5_encode(str(rnd2))
61 | challenge = md5_str1 + md5_str2[0:2]
62 | return challenge
63 |
64 | def _make_response_format(self, success=1, challenge=None, new_captcha=1):
65 | if not challenge:
66 | challenge = self._make_fail_challenge()
67 | if new_captcha:
68 | string_format = json.dumps(
69 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": True})
70 | else:
71 | string_format = json.dumps(
72 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": False})
73 | return string_format
74 |
75 | def _register_challenge(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
76 | if user_id:
77 | 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(
78 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id,
79 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
80 | else:
81 | register_url = "{api_url}{handler}?gt={captcha_ID}&json_format={JSON_FORMAT}&client_type={client_type}&ip_address={ip_address}".format(
82 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id,
83 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
84 | try:
85 | response = requests.get(register_url, timeout=2)
86 | if response.status_code == requests.codes.ok:
87 | res_string = response.text
88 | else:
89 | res_string = ""
90 | except:
91 | res_string = ""
92 | return res_string
93 |
94 | def success_validate(self, challenge, validate, seccode, user_id=None, gt=None, data='', userinfo='',
95 | JSON_FORMAT=1):
96 | """
97 | 正常模式的二次验证方式.向geetest server 请求验证结果.
98 | """
99 | if not self._check_para(challenge, validate, seccode):
100 | return 0
101 | if not self._check_result(challenge, validate):
102 | return 0
103 | validate_url = "{api_url}{handler}".format(
104 | api_url=self.API_URL, handler=self.VALIDATE_HANDLER)
105 | query = {
106 | "seccode": seccode,
107 | "sdk": ''.join(["python_", self.sdk_version]),
108 | "user_id": user_id,
109 | "data": data,
110 | "timestamp": time.time(),
111 | "challenge": challenge,
112 | "userinfo": userinfo,
113 | "captchaid": gt,
114 | "json_format": JSON_FORMAT
115 | }
116 | backinfo = self._post_values(validate_url, query)
117 | if JSON_FORMAT == 1:
118 | backinfo = json.loads(backinfo)
119 | backinfo = backinfo["seccode"]
120 | if backinfo == self._md5_encode(seccode):
121 | return 1
122 | else:
123 | return 0
124 |
125 | def _post_values(self, apiserver, data):
126 | response = requests.post(apiserver, data)
127 | return response.text
128 |
129 | def _check_result(self, origin, validate):
130 | encodeStr = self._md5_encode(self.private_key + "geetest" + origin)
131 | if validate == encodeStr:
132 | return True
133 | else:
134 | return False
135 |
136 | def failback_validate(self, challenge, validate, seccode):
137 | """
138 | failback模式的二次验证方式.在本地对轨迹进行简单的判断返回验证结果.
139 | """
140 | if not self._check_para(challenge, validate, seccode):
141 | return 0
142 | validate_result = self._failback_check_result(
143 | challenge, validate, )
144 | return validate_result
145 |
146 | def _failback_check_result(self, challenge, validate):
147 | encodeStr = self._md5_encode(challenge)
148 | if validate == encodeStr:
149 | return True
150 | else:
151 | return False
152 |
153 | def _check_para(self, challenge, validate, seccode):
154 | return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip()))
155 |
156 | def _md5_encode(self, values):
157 | if type(values) == str:
158 | values = values.encode()
159 | m = md5(values)
160 | return m.hexdigest()
161 |
--------------------------------------------------------------------------------
/demo/flask_demo/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | requests
--------------------------------------------------------------------------------
/demo/flask_demo/start.py:
--------------------------------------------------------------------------------
1 | import json
2 | from flask import session, make_response, Flask, request, render_template
3 |
4 | from geetest import GeetestLib
5 |
6 | # 请在官网申请ID使用,示例ID不可使用
7 | pc_geetest_id = "48a6ebac4ebc6642d68c217fca33eb4d"
8 | pc_geetest_key = "4f1c085290bec5afdc54df73535fc361"
9 |
10 | mobile_geetest_id = "48a6ebac4ebc6642d68c217fca33eb4d"
11 | mobile_geetest_key = "4f1c085290bec5afdc54df73535fc361"
12 |
13 | app = Flask(__name__)
14 | app.config.update(
15 | DEBUG=True,
16 | )
17 |
18 |
19 | @app.route('/pc-geetest/register', methods=["GET"])
20 | def get_pc_captcha():
21 | user_id = 'test'
22 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
23 | status = gt.pre_process(user_id)
24 | session[gt.GT_STATUS_SESSION_KEY] = status
25 | session["user_id"] = user_id
26 | response_str = gt.get_response_str()
27 | return response_str
28 |
29 |
30 | @app.route('/mobile-geetest/register', methods=["GET"])
31 | def get_mobile_captcha():
32 | user_id = 'test'
33 | gt = GeetestLib(mobile_geetest_id, mobile_geetest_key)
34 | status = gt.pre_process(user_id)
35 | session[gt.GT_STATUS_SESSION_KEY] = status
36 | session["user_id"] = user_id
37 | response_str = gt.get_response_str()
38 | return response_str
39 |
40 |
41 | @app.route('/pc-geetest/validate', methods=["POST"])
42 | def pc_validate_captcha():
43 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
44 | challenge = request.form[gt.FN_CHALLENGE]
45 | validate = request.form[gt.FN_VALIDATE]
46 | seccode = request.form[gt.FN_SECCODE]
47 | status = session[gt.GT_STATUS_SESSION_KEY]
48 | user_id = session["user_id"]
49 | if status:
50 | result = gt.success_validate(challenge, validate, seccode, user_id)
51 | else:
52 | result = gt.failback_validate(challenge, validate, seccode)
53 | result = "登录成功
" if result else "登录失败
"
54 | return result
55 |
56 |
57 | @app.route('/pc-geetest/ajax_validate', methods=["POST"])
58 | def pc_ajax_validate():
59 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
60 | challenge = request.form[gt.FN_CHALLENGE]
61 | validate = request.form[gt.FN_VALIDATE]
62 | seccode = request.form[gt.FN_SECCODE]
63 | status = session[gt.GT_STATUS_SESSION_KEY]
64 | user_id = session["user_id"]
65 | if status:
66 | result = gt.success_validate(challenge, validate, seccode, user_id, data='', userinfo='')
67 | else:
68 | result = gt.failback_validate(challenge, validate, seccode)
69 | result = {"status": "success"} if result else {"status": "fail"}
70 | return json.dumps(result)
71 |
72 |
73 | @app.route('/mobile-geetest/ajax_validate', methods=["POST"])
74 | def mobile_ajax_validate():
75 | gt = GeetestLib(mobile_geetest_id, mobile_geetest_key)
76 | challenge = request.form[gt.FN_CHALLENGE]
77 | validate = request.form[gt.FN_VALIDATE]
78 | seccode = request.form[gt.FN_SECCODE]
79 | status = session[gt.GT_STATUS_SESSION_KEY]
80 | user_id = session["user_id"]
81 | if status:
82 | result = gt.success_validate(challenge, validate, seccode, user_id, data='', userinfo='')
83 | else:
84 | result = gt.failback_validate(challenge, validate, seccode)
85 | result = {"status": "success"} if result else {"status": "fail"}
86 | return json.dumps(result)
87 |
88 |
89 | @app.route('/')
90 | def login():
91 | return render_template('login.html')
92 |
93 |
94 | if __name__ == '__main__':
95 | app.secret_key = 'i-like-python'
96 | app.run()
97 |
--------------------------------------------------------------------------------
/demo/flask_demo/static/gt.js:
--------------------------------------------------------------------------------
1 | "v0.4.8 Geetest Inc.";
2 |
3 | (function (window) {
4 | "use strict";
5 | if (typeof window === 'undefined') {
6 | throw new Error('Geetest requires browser environment');
7 | }
8 |
9 | var document = window.document;
10 | var Math = window.Math;
11 | var head = document.getElementsByTagName("head")[0];
12 |
13 | function _Object(obj) {
14 | this._obj = obj;
15 | }
16 |
17 | _Object.prototype = {
18 | _each: function (process) {
19 | var _obj = this._obj;
20 | for (var k in _obj) {
21 | if (_obj.hasOwnProperty(k)) {
22 | process(k, _obj[k]);
23 | }
24 | }
25 | return this;
26 | }
27 | };
28 |
29 | function Config(config) {
30 | var self = this;
31 | new _Object(config)._each(function (key, value) {
32 | self[key] = value;
33 | });
34 | }
35 |
36 | Config.prototype = {
37 | api_server: 'api.geetest.com',
38 | protocol: 'http://',
39 | typePath: '/gettype.php',
40 | fallback_config: {
41 | slide: {
42 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
43 | type: 'slide',
44 | slide: '/static/js/geetest.0.0.0.js'
45 | },
46 | fullpage: {
47 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
48 | type: 'fullpage',
49 | fullpage: '/static/js/fullpage.0.0.0.js'
50 | }
51 | },
52 | _get_fallback_config: function () {
53 | var self = this;
54 | if (isString(self.type)) {
55 | return self.fallback_config[self.type];
56 | } else if (self.new_captcha) {
57 | return self.fallback_config.fullpage;
58 | } else {
59 | return self.fallback_config.slide;
60 | }
61 | },
62 | _extend: function (obj) {
63 | var self = this;
64 | new _Object(obj)._each(function (key, value) {
65 | self[key] = value;
66 | })
67 | }
68 | };
69 | var isNumber = function (value) {
70 | return (typeof value === 'number');
71 | };
72 | var isString = function (value) {
73 | return (typeof value === 'string');
74 | };
75 | var isBoolean = function (value) {
76 | return (typeof value === 'boolean');
77 | };
78 | var isObject = function (value) {
79 | return (typeof value === 'object' && value !== null);
80 | };
81 | var isFunction = function (value) {
82 | return (typeof value === 'function');
83 | };
84 | var MOBILE = /Mobi/i.test(navigator.userAgent);
85 | var pt = MOBILE ? 3 : 0;
86 |
87 | var callbacks = {};
88 | var status = {};
89 |
90 | var nowDate = function () {
91 | var date = new Date();
92 | var year = date.getFullYear();
93 | var month = date.getMonth() + 1;
94 | var day = date.getDate();
95 | var hours = date.getHours();
96 | var minutes = date.getMinutes();
97 | var seconds = date.getSeconds();
98 |
99 | if (month >= 1 && month <= 9) {
100 | month = '0' + month;
101 | }
102 | if (day >= 0 && day <= 9) {
103 | day = '0' + day;
104 | }
105 | if (hours >= 0 && hours <= 9) {
106 | hours = '0' + hours;
107 | }
108 | if (minutes >= 0 && minutes <= 9) {
109 | minutes = '0' + minutes;
110 | }
111 | if (seconds >= 0 && seconds <= 9) {
112 | seconds = '0' + seconds;
113 | }
114 | var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds;
115 | return currentdate;
116 | }
117 |
118 | var random = function () {
119 | return parseInt(Math.random() * 10000) + (new Date()).valueOf();
120 | };
121 |
122 | var loadScript = function (url, cb) {
123 | var script = document.createElement("script");
124 | script.charset = "UTF-8";
125 | script.async = true;
126 |
127 | // 对geetest的静态资源添加 crossOrigin
128 | if ( /static\.geetest\.com/g.test(url)) {
129 | script.crossOrigin = "anonymous";
130 | }
131 |
132 | script.onerror = function () {
133 | cb(true);
134 | };
135 | var loaded = false;
136 | script.onload = script.onreadystatechange = function () {
137 | if (!loaded &&
138 | (!script.readyState ||
139 | "loaded" === script.readyState ||
140 | "complete" === script.readyState)) {
141 |
142 | loaded = true;
143 | setTimeout(function () {
144 | cb(false);
145 | }, 0);
146 | }
147 | };
148 | script.src = url;
149 | head.appendChild(script);
150 | };
151 |
152 | var normalizeDomain = function (domain) {
153 | // special domain: uems.sysu.edu.cn/jwxt/geetest/
154 | // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
155 | return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
156 | };
157 | var normalizePath = function (path) {
158 | path = path.replace(/\/+/g, '/');
159 | if (path.indexOf('/') !== 0) {
160 | path = '/' + path;
161 | }
162 | return path;
163 | };
164 | var normalizeQuery = function (query) {
165 | if (!query) {
166 | return '';
167 | }
168 | var q = '?';
169 | new _Object(query)._each(function (key, value) {
170 | if (isString(value) || isNumber(value) || isBoolean(value)) {
171 | q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
172 | }
173 | });
174 | if (q === '?') {
175 | q = '';
176 | }
177 | return q.replace(/&$/, '');
178 | };
179 | var makeURL = function (protocol, domain, path, query) {
180 | domain = normalizeDomain(domain);
181 |
182 | var url = normalizePath(path) + normalizeQuery(query);
183 | if (domain) {
184 | url = protocol + domain + url;
185 | }
186 |
187 | return url;
188 | };
189 |
190 | var load = function (config, send, protocol, domains, path, query, cb) {
191 | var tryRequest = function (at) {
192 |
193 | var url = makeURL(protocol, domains[at], path, query);
194 | loadScript(url, function (err) {
195 | if (err) {
196 | if (at >= domains.length - 1) {
197 | cb(true);
198 | // report gettype error
199 | if (send) {
200 | config.error_code = 508;
201 | var url = protocol + domains[at] + path;
202 | reportError(config, url);
203 | }
204 | } else {
205 | tryRequest(at + 1);
206 | }
207 | } else {
208 | cb(false);
209 | }
210 | });
211 | };
212 | tryRequest(0);
213 | };
214 |
215 |
216 | var jsonp = function (domains, path, config, callback) {
217 | if (isObject(config.getLib)) {
218 | config._extend(config.getLib);
219 | callback(config);
220 | return;
221 | }
222 | if (config.offline) {
223 | callback(config._get_fallback_config());
224 | return;
225 | }
226 |
227 | var cb = "geetest_" + random();
228 | window[cb] = function (data) {
229 | if (data.status == 'success') {
230 | callback(data.data);
231 | } else if (!data.status) {
232 | callback(data);
233 | } else {
234 | callback(config._get_fallback_config());
235 | }
236 | window[cb] = undefined;
237 | try {
238 | delete window[cb];
239 | } catch (e) {
240 | }
241 | };
242 | load(config, true, config.protocol, domains, path, {
243 | gt: config.gt,
244 | callback: cb
245 | }, function (err) {
246 | if (err) {
247 | callback(config._get_fallback_config());
248 | }
249 | });
250 | };
251 |
252 | var reportError = function (config, url) {
253 | load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
254 | time: nowDate(),
255 | captcha_id: config.gt,
256 | challenge: config.challenge,
257 | pt: pt,
258 | exception_url: url,
259 | error_code: config.error_code
260 | }, function (err) {})
261 | }
262 |
263 | var throwError = function (errorType, config) {
264 | var errors = {
265 | networkError: '网络错误',
266 | gtTypeError: 'gt字段不是字符串类型'
267 | };
268 | if (typeof config.onError === 'function') {
269 | config.onError(errors[errorType]);
270 | } else {
271 | throw new Error(errors[errorType]);
272 | }
273 | };
274 |
275 | var detect = function () {
276 | return window.Geetest || document.getElementById("gt_lib");
277 | };
278 |
279 | if (detect()) {
280 | status.slide = "loaded";
281 | }
282 |
283 | window.initGeetest = function (userConfig, callback) {
284 |
285 | var config = new Config(userConfig);
286 |
287 | if (userConfig.https) {
288 | config.protocol = 'https://';
289 | } else if (!userConfig.protocol) {
290 | config.protocol = window.location.protocol + '//';
291 | }
292 |
293 | // for KFC
294 | if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' ||
295 | userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') {
296 | config.apiserver = 'yumchina.geetest.com/'; // for old js
297 | config.api_server = 'yumchina.geetest.com';
298 | }
299 |
300 | if(userConfig.gt){
301 | window.GeeGT = userConfig.gt
302 | }
303 |
304 | if(userConfig.challenge){
305 | window.GeeChallenge = userConfig.challenge
306 | }
307 |
308 | if (isObject(userConfig.getType)) {
309 | config._extend(userConfig.getType);
310 | }
311 | jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) {
312 | var type = newConfig.type;
313 | var init = function () {
314 | config._extend(newConfig);
315 | callback(new window.Geetest(config));
316 | };
317 |
318 | callbacks[type] = callbacks[type] || [];
319 | var s = status[type] || 'init';
320 | if (s === 'init') {
321 | status[type] = 'loading';
322 |
323 | callbacks[type].push(init);
324 |
325 | load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
326 | if (err) {
327 | status[type] = 'fail';
328 | throwError('networkError', config);
329 | } else {
330 | status[type] = 'loaded';
331 | var cbs = callbacks[type];
332 | for (var i = 0, len = cbs.length; i < len; i = i + 1) {
333 | var cb = cbs[i];
334 | if (isFunction(cb)) {
335 | cb();
336 | }
337 | }
338 | callbacks[type] = [];
339 | }
340 | });
341 | } else if (s === "loaded") {
342 | init();
343 | } else if (s === "fail") {
344 | throwError('networkError', config);
345 | } else if (s === "loading") {
346 | callbacks[type].push(init);
347 | }
348 | });
349 |
350 | };
351 |
352 |
353 | })(window);
354 |
355 |
--------------------------------------------------------------------------------
/demo/flask_demo/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | gt-python-flask-demo
7 |
65 |
66 |
67 | 极验验证SDKDemo
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
98 |
99 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/demo/tornado_demo/geetest/__init__.py:
--------------------------------------------------------------------------------
1 | from .geetest import GeetestLib, VERSION
--------------------------------------------------------------------------------
/demo/tornado_demo/geetest/geetest.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import random
3 | import json
4 | import requests
5 | import time
6 | from hashlib import md5
7 |
8 | if sys.version_info >= (3,):
9 | xrange = range
10 |
11 | VERSION = "3.0.0"
12 |
13 |
14 | class GeetestLib(object):
15 | FN_CHALLENGE = "geetest_challenge"
16 | FN_VALIDATE = "geetest_validate"
17 | FN_SECCODE = "geetest_seccode"
18 |
19 | GT_STATUS_SESSION_KEY = "gt_server_status"
20 |
21 | API_URL = "http://api.geetest.com"
22 | REGISTER_HANDLER = "/register.php"
23 | VALIDATE_HANDLER = "/validate.php"
24 | JSON_FORMAT = False
25 |
26 | def __init__(self, captcha_id, private_key):
27 | self.private_key = private_key
28 | self.captcha_id = captcha_id
29 | self.sdk_version = VERSION
30 | self._response_str = ""
31 |
32 | def pre_process(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
33 | status, challenge = self._register(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
34 | self._response_str = self._make_response_format(status, challenge, new_captcha)
35 | return status
36 |
37 | def _register(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
38 | pri_responce = self._register_challenge(user_id, new_captcha, JSON_FORMAT, client_type, ip_address)
39 | if pri_responce:
40 | if JSON_FORMAT == 1:
41 | response_dic = json.loads(pri_responce)
42 | challenge = response_dic["challenge"]
43 | else:
44 | challenge = pri_responce
45 | else:
46 | challenge = " "
47 | if len(challenge) == 32:
48 | challenge = self._md5_encode("".join([challenge, self.private_key]))
49 | return 1, challenge
50 | else:
51 | return 0, self._make_fail_challenge()
52 |
53 | def get_response_str(self):
54 | return self._response_str
55 |
56 | def _make_fail_challenge(self):
57 | rnd1 = random.randint(0, 99)
58 | rnd2 = random.randint(0, 99)
59 | md5_str1 = self._md5_encode(str(rnd1))
60 | md5_str2 = self._md5_encode(str(rnd2))
61 | challenge = md5_str1 + md5_str2[0:2]
62 | return challenge
63 |
64 | def _make_response_format(self, success=1, challenge=None, new_captcha=1):
65 | if not challenge:
66 | challenge = self._make_fail_challenge()
67 | if new_captcha:
68 | string_format = json.dumps(
69 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": True})
70 | else:
71 | string_format = json.dumps(
72 | {'success': success, 'gt': self.captcha_id, 'challenge': challenge, "new_captcha": False})
73 | return string_format
74 |
75 | def _register_challenge(self, user_id=None, new_captcha=1, JSON_FORMAT=1, client_type="web", ip_address=""):
76 | if user_id:
77 | 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(
78 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id, user_id=user_id,
79 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
80 | else:
81 | register_url = "{api_url}{handler}?gt={captcha_ID}&json_format={JSON_FORMAT}&client_type={client_type}&ip_address={ip_address}".format(
82 | api_url=self.API_URL, handler=self.REGISTER_HANDLER, captcha_ID=self.captcha_id,
83 | new_captcha=new_captcha, JSON_FORMAT=JSON_FORMAT, client_type=client_type, ip_address=ip_address)
84 | try:
85 | response = requests.get(register_url, timeout=2)
86 | if response.status_code == requests.codes.ok:
87 | res_string = response.text
88 | else:
89 | res_string = ""
90 | except:
91 | res_string = ""
92 | return res_string
93 |
94 | def success_validate(self, challenge, validate, seccode, user_id=None, gt=None, data='', userinfo='',
95 | JSON_FORMAT=1):
96 | """
97 | 正常模式的二次验证方式.向geetest server 请求验证结果.
98 | """
99 | if not self._check_para(challenge, validate, seccode):
100 | return 0
101 | if not self._check_result(challenge, validate):
102 | return 0
103 | validate_url = "{api_url}{handler}".format(
104 | api_url=self.API_URL, handler=self.VALIDATE_HANDLER)
105 | query = {
106 | "seccode": seccode,
107 | "sdk": ''.join(["python_", self.sdk_version]),
108 | "user_id": user_id,
109 | "data": data,
110 | "timestamp": time.time(),
111 | "challenge": challenge,
112 | "userinfo": userinfo,
113 | "captchaid": gt,
114 | "json_format": JSON_FORMAT
115 | }
116 | backinfo = self._post_values(validate_url, query)
117 | if JSON_FORMAT == 1:
118 | backinfo = json.loads(backinfo)
119 | backinfo = backinfo["seccode"]
120 | if backinfo == self._md5_encode(seccode):
121 | return 1
122 | else:
123 | return 0
124 |
125 | def _post_values(self, apiserver, data):
126 | response = requests.post(apiserver, data)
127 | return response.text
128 |
129 | def _check_result(self, origin, validate):
130 | encodeStr = self._md5_encode(self.private_key + "geetest" + origin)
131 | if validate == encodeStr:
132 | return True
133 | else:
134 | return False
135 |
136 | def failback_validate(self, challenge, validate, seccode):
137 | """
138 | failback模式的二次验证方式.在本地对轨迹进行简单的判断返回验证结果.
139 | """
140 | if not self._check_para(challenge, validate, seccode):
141 | return 0
142 | validate_result = self._failback_check_result(
143 | challenge, validate, )
144 | return validate_result
145 |
146 | def _failback_check_result(self, challenge, validate):
147 | encodeStr = self._md5_encode(challenge)
148 | if validate == encodeStr:
149 | return True
150 | else:
151 | return False
152 |
153 | def _check_para(self, challenge, validate, seccode):
154 | return (bool(challenge.strip()) and bool(validate.strip()) and bool(seccode.strip()))
155 |
156 | def _md5_encode(self, values):
157 | if type(values) == str:
158 | values = values.encode()
159 | m = md5(values)
160 | return m.hexdigest()
161 |
--------------------------------------------------------------------------------
/demo/tornado_demo/requirements.txt:
--------------------------------------------------------------------------------
1 | torndsession
2 | requests
3 |
--------------------------------------------------------------------------------
/demo/tornado_demo/start.py:
--------------------------------------------------------------------------------
1 | import json
2 | import tornado.gen
3 | import tornado.ioloop
4 | import tornado.web
5 | from torndsession.session import SessionManager
6 | from torndsession.sessionhandler import SessionBaseHandler
7 |
8 | from geetest import GeetestLib
9 |
10 | #请在官网申请ID使用,示例ID不可使用
11 | pc_geetest_id = "48a6ebac4ebc6642d68c217fca33eb4d"
12 | pc_geetest_key = "4f1c085290bec5afdc54df73535fc361"
13 |
14 | product = "embed"
15 |
16 |
17 | class MainHandler(tornado.web.RequestHandler):
18 | def get(self):
19 | self.render("static/login.html",)
20 |
21 | class JsHandler(tornado.web.RequestHandler):
22 | def get(self):
23 | self.render("static/gt.js",)
24 |
25 |
26 | class PcGetCaptchaHandler(SessionBaseHandler):
27 | def get(self):
28 | user_id = 'test'
29 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
30 | status = gt.pre_process(user_id,JSON_FORMAT=0,ip_address="127.0.0.1")
31 | if not status:
32 | status=2
33 | self.session[gt.GT_STATUS_SESSION_KEY] = status
34 | self.session["user_id"] = user_id
35 | response_str = gt.get_response_str()
36 | self.write(response_str)
37 |
38 |
39 | class PcValidateHandler(SessionBaseHandler):
40 | def post(self):
41 | gt = GeetestLib(pc_geetest_id, pc_geetest_key)
42 | challenge = self.get_argument(gt.FN_CHALLENGE, "")
43 | validate = self.get_argument(gt.FN_VALIDATE, "")
44 | seccode = self.get_argument(gt.FN_SECCODE, "")
45 | status = self.session[gt.GT_STATUS_SESSION_KEY]
46 | user_id = self.session["user_id"]
47 | if status==1:
48 | result = gt.success_validate(challenge, validate, seccode, user_id,JSON_FORMAT=0)
49 | else:
50 | result = gt.failback_validate(challenge, validate, seccode)
51 | self.session["user_id"] = user_id
52 | result = "登录成功
" if result else "登录失败
"
53 | self.write(result)
54 |
55 | if __name__ == "__main__":
56 | app = tornado.web.Application([
57 | (r"/", MainHandler),
58 | (r"/static/gt.js",JsHandler),
59 | (r"/pc-geetest/register", PcGetCaptchaHandler),
60 | (r"/pc-geetest/validate", PcValidateHandler),
61 | ], debug=True)
62 |
63 | app.listen(8088)
64 | tornado.ioloop.IOLoop.instance().start()
65 |
--------------------------------------------------------------------------------
/demo/tornado_demo/static/gt.js:
--------------------------------------------------------------------------------
1 | "v0.4.8 Geetest Inc.";
2 |
3 | (function (window) {
4 | "use strict";
5 | if (typeof window === 'undefined') {
6 | throw new Error('Geetest requires browser environment');
7 | }
8 |
9 | var document = window.document;
10 | var Math = window.Math;
11 | var head = document.getElementsByTagName("head")[0];
12 |
13 | function _Object(obj) {
14 | this._obj = obj;
15 | }
16 |
17 | _Object.prototype = {
18 | _each: function (process) {
19 | var _obj = this._obj;
20 | for (var k in _obj) {
21 | if (_obj.hasOwnProperty(k)) {
22 | process(k, _obj[k]);
23 | }
24 | }
25 | return this;
26 | }
27 | };
28 |
29 | function Config(config) {
30 | var self = this;
31 | new _Object(config)._each(function (key, value) {
32 | self[key] = value;
33 | });
34 | }
35 |
36 | Config.prototype = {
37 | api_server: 'api.geetest.com',
38 | protocol: 'http://',
39 | typePath: '/gettype.php',
40 | fallback_config: {
41 | slide: {
42 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
43 | type: 'slide',
44 | slide: '/static/js/geetest.0.0.0.js'
45 | },
46 | fullpage: {
47 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
48 | type: 'fullpage',
49 | fullpage: '/static/js/fullpage.0.0.0.js'
50 | }
51 | },
52 | _get_fallback_config: function () {
53 | var self = this;
54 | if (isString(self.type)) {
55 | return self.fallback_config[self.type];
56 | } else if (self.new_captcha) {
57 | return self.fallback_config.fullpage;
58 | } else {
59 | return self.fallback_config.slide;
60 | }
61 | },
62 | _extend: function (obj) {
63 | var self = this;
64 | new _Object(obj)._each(function (key, value) {
65 | self[key] = value;
66 | })
67 | }
68 | };
69 | var isNumber = function (value) {
70 | return (typeof value === 'number');
71 | };
72 | var isString = function (value) {
73 | return (typeof value === 'string');
74 | };
75 | var isBoolean = function (value) {
76 | return (typeof value === 'boolean');
77 | };
78 | var isObject = function (value) {
79 | return (typeof value === 'object' && value !== null);
80 | };
81 | var isFunction = function (value) {
82 | return (typeof value === 'function');
83 | };
84 | var MOBILE = /Mobi/i.test(navigator.userAgent);
85 | var pt = MOBILE ? 3 : 0;
86 |
87 | var callbacks = {};
88 | var status = {};
89 |
90 | var nowDate = function () {
91 | var date = new Date();
92 | var year = date.getFullYear();
93 | var month = date.getMonth() + 1;
94 | var day = date.getDate();
95 | var hours = date.getHours();
96 | var minutes = date.getMinutes();
97 | var seconds = date.getSeconds();
98 |
99 | if (month >= 1 && month <= 9) {
100 | month = '0' + month;
101 | }
102 | if (day >= 0 && day <= 9) {
103 | day = '0' + day;
104 | }
105 | if (hours >= 0 && hours <= 9) {
106 | hours = '0' + hours;
107 | }
108 | if (minutes >= 0 && minutes <= 9) {
109 | minutes = '0' + minutes;
110 | }
111 | if (seconds >= 0 && seconds <= 9) {
112 | seconds = '0' + seconds;
113 | }
114 | var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds;
115 | return currentdate;
116 | }
117 |
118 | var random = function () {
119 | return parseInt(Math.random() * 10000) + (new Date()).valueOf();
120 | };
121 |
122 | var loadScript = function (url, cb) {
123 | var script = document.createElement("script");
124 | script.charset = "UTF-8";
125 | script.async = true;
126 |
127 | // 对geetest的静态资源添加 crossOrigin
128 | if ( /static\.geetest\.com/g.test(url)) {
129 | script.crossOrigin = "anonymous";
130 | }
131 |
132 | script.onerror = function () {
133 | cb(true);
134 | };
135 | var loaded = false;
136 | script.onload = script.onreadystatechange = function () {
137 | if (!loaded &&
138 | (!script.readyState ||
139 | "loaded" === script.readyState ||
140 | "complete" === script.readyState)) {
141 |
142 | loaded = true;
143 | setTimeout(function () {
144 | cb(false);
145 | }, 0);
146 | }
147 | };
148 | script.src = url;
149 | head.appendChild(script);
150 | };
151 |
152 | var normalizeDomain = function (domain) {
153 | // special domain: uems.sysu.edu.cn/jwxt/geetest/
154 | // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn
155 | return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest
156 | };
157 | var normalizePath = function (path) {
158 | path = path.replace(/\/+/g, '/');
159 | if (path.indexOf('/') !== 0) {
160 | path = '/' + path;
161 | }
162 | return path;
163 | };
164 | var normalizeQuery = function (query) {
165 | if (!query) {
166 | return '';
167 | }
168 | var q = '?';
169 | new _Object(query)._each(function (key, value) {
170 | if (isString(value) || isNumber(value) || isBoolean(value)) {
171 | q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
172 | }
173 | });
174 | if (q === '?') {
175 | q = '';
176 | }
177 | return q.replace(/&$/, '');
178 | };
179 | var makeURL = function (protocol, domain, path, query) {
180 | domain = normalizeDomain(domain);
181 |
182 | var url = normalizePath(path) + normalizeQuery(query);
183 | if (domain) {
184 | url = protocol + domain + url;
185 | }
186 |
187 | return url;
188 | };
189 |
190 | var load = function (config, send, protocol, domains, path, query, cb) {
191 | var tryRequest = function (at) {
192 |
193 | var url = makeURL(protocol, domains[at], path, query);
194 | loadScript(url, function (err) {
195 | if (err) {
196 | if (at >= domains.length - 1) {
197 | cb(true);
198 | // report gettype error
199 | if (send) {
200 | config.error_code = 508;
201 | var url = protocol + domains[at] + path;
202 | reportError(config, url);
203 | }
204 | } else {
205 | tryRequest(at + 1);
206 | }
207 | } else {
208 | cb(false);
209 | }
210 | });
211 | };
212 | tryRequest(0);
213 | };
214 |
215 |
216 | var jsonp = function (domains, path, config, callback) {
217 | if (isObject(config.getLib)) {
218 | config._extend(config.getLib);
219 | callback(config);
220 | return;
221 | }
222 | if (config.offline) {
223 | callback(config._get_fallback_config());
224 | return;
225 | }
226 |
227 | var cb = "geetest_" + random();
228 | window[cb] = function (data) {
229 | if (data.status == 'success') {
230 | callback(data.data);
231 | } else if (!data.status) {
232 | callback(data);
233 | } else {
234 | callback(config._get_fallback_config());
235 | }
236 | window[cb] = undefined;
237 | try {
238 | delete window[cb];
239 | } catch (e) {
240 | }
241 | };
242 | load(config, true, config.protocol, domains, path, {
243 | gt: config.gt,
244 | callback: cb
245 | }, function (err) {
246 | if (err) {
247 | callback(config._get_fallback_config());
248 | }
249 | });
250 | };
251 |
252 | var reportError = function (config, url) {
253 | load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', {
254 | time: nowDate(),
255 | captcha_id: config.gt,
256 | challenge: config.challenge,
257 | pt: pt,
258 | exception_url: url,
259 | error_code: config.error_code
260 | }, function (err) {})
261 | }
262 |
263 | var throwError = function (errorType, config) {
264 | var errors = {
265 | networkError: '网络错误',
266 | gtTypeError: 'gt字段不是字符串类型'
267 | };
268 | if (typeof config.onError === 'function') {
269 | config.onError(errors[errorType]);
270 | } else {
271 | throw new Error(errors[errorType]);
272 | }
273 | };
274 |
275 | var detect = function () {
276 | return window.Geetest || document.getElementById("gt_lib");
277 | };
278 |
279 | if (detect()) {
280 | status.slide = "loaded";
281 | }
282 |
283 | window.initGeetest = function (userConfig, callback) {
284 |
285 | var config = new Config(userConfig);
286 |
287 | if (userConfig.https) {
288 | config.protocol = 'https://';
289 | } else if (!userConfig.protocol) {
290 | config.protocol = window.location.protocol + '//';
291 | }
292 |
293 | // for KFC
294 | if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' ||
295 | userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') {
296 | config.apiserver = 'yumchina.geetest.com/'; // for old js
297 | config.api_server = 'yumchina.geetest.com';
298 | }
299 |
300 | if(userConfig.gt){
301 | window.GeeGT = userConfig.gt
302 | }
303 |
304 | if(userConfig.challenge){
305 | window.GeeChallenge = userConfig.challenge
306 | }
307 |
308 | if (isObject(userConfig.getType)) {
309 | config._extend(userConfig.getType);
310 | }
311 | jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) {
312 | var type = newConfig.type;
313 | var init = function () {
314 | config._extend(newConfig);
315 | callback(new window.Geetest(config));
316 | };
317 |
318 | callbacks[type] = callbacks[type] || [];
319 | var s = status[type] || 'init';
320 | if (s === 'init') {
321 | status[type] = 'loading';
322 |
323 | callbacks[type].push(init);
324 |
325 | load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
326 | if (err) {
327 | status[type] = 'fail';
328 | throwError('networkError', config);
329 | } else {
330 | status[type] = 'loaded';
331 | var cbs = callbacks[type];
332 | for (var i = 0, len = cbs.length; i < len; i = i + 1) {
333 | var cb = cbs[i];
334 | if (isFunction(cb)) {
335 | cb();
336 | }
337 | }
338 | callbacks[type] = [];
339 | }
340 | });
341 | } else if (s === "loaded") {
342 | init();
343 | } else if (s === "fail") {
344 | throwError('networkError', config);
345 | } else if (s === "loading") {
346 | callbacks[type].push(init);
347 | }
348 | });
349 |
350 | };
351 |
352 |
353 | })(window);
354 |
355 |
--------------------------------------------------------------------------------
/demo/tornado_demo/static/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | gt-python-tornado-demo
7 |
65 |
66 |
67 | 极验验证SDKDemo
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
99 |
100 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------