顶象滑块验证码
一、服务接入流程
二、无感验证后端接入(业务应用集成)
- 访问顶象官网,注册账号后登录控制台,访问“无感验证”模块,申请开通后系统会分配一个唯一的AppId、AppSecret。
- 当用户滑动验证码通过后,验证码服务会生成一个
token
,用户的业务请求带上这个验证码token
,业务系统再调用后台 SDK 验证token
的有效性。
|
| 用户业务请求 | ----> | 业务系统 | ----> | | 验证码服务
(请求带上验证码token) | (获取token,调用验证码接口) | | (校验token有效性) |
顶象提供后端SDK来校验token是否合法 ,目前支持JAVA版、PHP版、C#版、Python版。
token验证api返回数据
字段名 | 数据类型 | 描述 |
---|---|---|
success | Boolean | 是否成功,true/false |
msg | String | 错误信息 |
ip | String | token产生时,客户端的ip |
code | String | 错误code |
错误code说明
code | 描述 |
---|---|
1001 | 错误的APPID |
1002 | 签名错误,请核对APPID和APPSECRET是否正确 |
1003 | token不合法或者已经过期(token是一次性使用并且只有两分钟有效期) |
1004 | 参数错误,请核对后端使用的APPID是否和前端页面一致 |
1005 | verifyToken传入ip时,校验不通过,即token产生的ip和业务请求ip不一致 |
三、后端实现
# CaptchaResponse.py (第三方)
class CaptchaResponse:
result = False
serverStatus = ""
def __init__(self, result, serverStatus):
self.result = result
self.serverStatus = serverStatus
def setResult(self, result):
self.result = result
def setServerStatus(self, serverStatus):
self.serverStatus = serverStatus
# CaptchaClient.py (第三方)
from urllib import request
import hashlib
import json
from new.CaptchaResponse import CaptchaResponse
class CaptchaClient:
requestUrl = "https://cap.dingxiang-inc.com/api/tokenVerify"
timeout = 2
response = None
def __init__(self, appId, appSecret):
self.appId = appId
self.appSecret = appSecret
def setTimeOut(self, timeOut):
self.timeout = timeOut
def setCaptchaUrl(self, url):
self.requestUrl = url
def checkToken(self, token):
print(len(token) > 1024)
captchaResponse = CaptchaResponse(False, "")
"""
if (self.appId == "" or (self.appId is None) or self.appSecret == ""
or (self.appSecret is None) or token == "" or (token is None)
or not (len(token) > 1024)):
"""
if (self.appId == "" or (self.appId is None) or self.appSecret == ""
or (self.appSecret is None) or token == "" or (token is None)
or not (len(token) > 205)):
captchaResponse.setServerStatus("参数错误")
return captchaResponse.__dict__
arr = token.split(":")
print(arr)
constId = ""
if len(arr) == 2:
constId = arr[1]
str_key = self.appSecret + arr[0] + self.appSecret
sign = hashlib.md5(str(str_key).encode("utf8")).hexdigest()
req_url = self.requestUrl + '?appKey=' + self.appId + '&token=' + arr[
0] + '&constId=' + constId + "&sign=" + sign
try:
# self.response = urllib2.urlopen(req_url, timeout=self.timeout)
self.response = request.urlopen(req_url, timeout=self.timeout)
# self.response = requests.get(req_url, timeout=self.timeout)
print(self.response.code)
if self.response.code == 200:
result = self.response.read()
result = json.loads(result)
captchaResponse.setServerStatus("SERVER_SUCCESS")
captchaResponse.setResult(result["success"])
else:
captchaResponse.setResult(True)
captchaResponse.setServerStatus("server error: status=" + str(self.response.code))
return captchaResponse.__dict__
except Exception as e:
captchaResponse.setResult(True)
captchaResponse.setServerStatus("server error:" + e)
return captchaResponse.__dict__
finally:
self.close(self.response)
def close(self, response):
try:
if response != None:
response.close()
del response
except Exception as e:
print("close response error:" + e.message)
# TokenDemo.py(自定义测试)
from new.CaptchaClient import CaptchaClient
APP_ID = '693d3ef199e411d0ed62cb2a87d8bdde'
APP_SECRET = '5eea7b131502eece01409d8bd358f0d5'
if __name__ == '__main__':
captchaClient = CaptchaClient(APP_ID, APP_SECRET)
captchaClient.setTimeOut(2)
# 设置超时时间,默认2秒
# captchaClient.setCaptchaUrl("http://cap.dingxiang-inc.com/api/tokenVerify")
# 特殊情况可以额外指定服务器,默认情况下不需要设置
# 只能使用一次
token = 'token:11159D5F8D540AA73D207C5FF53EAD7906F1A01D3D9D63E044F1DBE3CE6FB117ECB81B1038A6755D455A0059164BC0D61462F6D0E55910FA0E27B1BF7F8FDA610512217CBC50B81B3A3DDDD2F0F06CD8:5df10ea2jLv7WP9YbNEIfgn3xFpmnRAMb818FAu1'
print(len(token))
response = captchaClient.checkToken(token)
print(response)
# print("serverStatus", response['serverStatus'])
# 确保验证状态是SERVER_SUCCESS,SDK中有容错机制,在网络出现异常的情况会返回通过
# print(response['result'])
if response.get('result') and response.get('serverStatus') == 'SERVER_SUCCESS':
# token验证通过,继续其他流程
print('成功')
pass
else:
# token验证失败,业务系统可以直接阻断该次请求或者继续弹验证码
print("失败")
pass
四、前端应用
常规参数
初始化时有若干参数,其中 appId
是必填的。
参数名 | 必填 | 类型 | 说明 |
---|---|---|---|
appId | 是 | String | 当前应用的唯一标识 |
type | 否 | String | 类型,目前只有一个选项 basic ,默认值为 basic 。 |
style | 否 | String | 样式,可选项有 embed (默认)、inline 、popup 、oneclick 四种,具体效果可参见线上demo。 |
inlineFloatPosition | 否 | String | 浮动层位置,仅当 style 的值为 inline 时有效,可选项有 up (默认)、down 两种,具体效果可参见线上demo。 |
oneClickFloatPosition | 否 | string | 浮动层位置,仅当 style 的值为 oneclick 时有效,可选项有 up ,当style 值为oneclick 且不传此参数,默认为弹出形式。 |
width | 否 | Number | 控件(滑动条)宽度,单位为像素,默认为 300 。 |
language | 否 | String | 语言,可选项有 cn (默认,中文)、en (英文)。 |
success | 否 | Function | 验证成功时的回调函数,会传入一个参数,值为本次验证的 token:constId ,接入方需在后续的验证中传回此项值。注:此回调函数包含无感验证成功及滑动验证成功。 |
fail | 否 | Function | 验证失败时的回调函数,会传入一个参数,值为出错信息。 |
方法
验证码实例具备以下方法:
-
reload()
重置当前验证码示例:
myCaptcha.reload()
-
show()
显示当前验证码。style
为popup
的验证码默认是隐藏的,需要接入方根据页面逻辑调用show()
方法将其显示。示例:
myCaptcha.show()
-
hide()
隐藏当前验证码示例:
myCaptcha.hide()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{# 验证码滑块#}
<script src="https://cdn.dingxiang-inc.com/ctu-group/captcha-ui/index.js"></script>
<style>
.f {
height: 500px;
}
.tan {
width: 600px;
margin: 0 auto;
line-height: 500px;
font: normal 60px 微软雅黑;
text-align: center;
}
.tan:hover {
border-radius: 5px;
border: 1px black solid;
box-shadow: 4px 6px WindowFrame;
}
</style>
</head>
<body>
<div id="c1"></div>
<div class="f">
<div id="btn-popup" class="tan">弹出</div>
</div>
</body>
<script>
var myCaptcha = _dx.Captcha(document.getElementById('c1'), {
{#appId: 'appId', //appId,在控制台中“应用管理”或“应用配置”模块获取#}
appId: '693d3ef199e411d0ed62cb2a87d8bdde',
style: 'popup', // 类型
success: function (token) {
console.log('token:', token);
myCaptcha.hide();
setTimeout(function () {
myCaptcha.reload();
}, 1000);
},
fail: function (error) {
console.log(error);
myCaptcha.reload();
},
});
document.getElementById('btn-popup').onclick = function () {
myCaptcha.show();
}
</script>
</html>
在当下的阶段,必将由程序员来主导,甚至比以往更甚。