-
背景
最近,项目后台上线后,有人觉得登录页的四位验证码有时候看不出来,需要刷新好几次填对;于是在搜索滑动验证时注意到了阿里云的这个人机验证功能;虽然也有好多网友提供实现方法,但是经过自己的操作,觉得自己整理一番,不仅可以帮助新手,也能作为自己以后的经验备忘,欢迎指摘 ...
了解概念,不然也找不到自己选择这个功能的理由吧:
滑动验证(No-Captcha,简称NC)
,是阿里巴巴集团打破传统验证码技术推出的最新人机识别服务。阿里云的滑动验证采用先进的风险分析引擎来区分来自人类与机器人的访问行为。用户通过类似滑动解锁的方式来通过人机验证,对用户来说无需思考即可通过人机识别(图灵测试)的挑战。环境:
框架: ThinkPHP5.1
系统:Nginx、Win10、CentOS7.2
㈠ 前期准备
- 首先,建议阅读【
人机滑动验证 官方文档
】,鄙人觉得里面介绍的很详细,作为指导博文,不可能全给摘过来的 - 既然考虑到使用人家的服务,当然得了解一下是不是免费啥的呗,0.002元/条,好在也是不贵吧?
- 【
创建 AccessKey (指导)
】,请使用子账号(RAM用户)AccessKey,并为子账号授予云盾人机验证权限(AliyunYundunAFSFullAccess) - 根据 【
滑动验证 —— 快速入门
】,在【云盾人机验证控制台
】开通、配置
㈡ 前端接入代码集成
首先,给出官方文档介绍【 滑动验证前端代码集成文档-PCWEB版
】,然后对比我的实际操作代码即可
- Html 核心代码 (至于样式的优化,文档中有,自行融合呗)
<!-- 国内使用 -->
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
<div id="your-dom-id" class="layui-form-item nc-container"></div>
<input type="hidden" class="nc_token" name="nc_token" value="X">
- js 核心代码:
var nc_appkey = "Your appkey";//写入自己的 appkey
var nc_token = [nc_appkey , (new Date()).getTime(), Math.random()].join(':');
var NC_Opt =
{
renderTo: "#your-dom-id",
appkey: nc_appkey ,
scene: "nc_login",
token: nc_token,
customWidth: 300,
trans:{"key1":"code0"},
elementID: ["usernameID"],
is_Opt: 0,
language: "cn",
isEnabled: true,
timeout: 3000,
times:5,
callback: function (data) {
//window.console && console.log(nc_token);
//console.log('sss',data);
//TODO 此处 toUrl 即为后台验证链接,根据自己的业务定义即可
var toUrl = "{:url('cms/login/ajaxAfsCheck')}";
$.post(
toUrl,
data,
function (result) {
if (result.status == 1) {
$(".nc_token").val(nc_token);
} else {
//失败
layer.msg(result.message);
}
}, "JSON");
}
};
var nc = new noCaptcha(NC_Opt);
nc.upLang('cn', {
_startTEXT: "请按住滑块,拖动到最右边",
_yesTEXT: "验证通过",
_error300: "哎呀,出错了,点击<a href=\"javascript:__nc.reset()\">刷新</a>再来一次",
_errorNetwork: "网络不给力,请<a href=\"javascript:__nc.reset()\">点击刷新</a>",
});
㈢ 服务端代码集成
此时可以根据 【滑动验证服务端代码集成文档
】,进行整合处理
- 在【
云盾·人机控制台
】下载对应语言的SDK
以鄙人的ThinkPHP5.1.2框架环境
,服务端 SDK代码放置位置参考:
- 应用服务器 请求处理类的设计:
此验证方法即为前端js中回调所触发的请求链接地址
注意:YOUR ACCESS_KEY、YOUR ACCESS_SECRET请替换成您的阿里云子账号(RAM用户)的 accesskey id和secret ; YOUR APP_KEY 写入自己的 appkey
/**
* ajax 测试阿里云滑动验证
* @param Request $request
* TODO YOUR ACCESS_KEY、YOUR ACCESS_SECRET请替换成您的阿里云子账号(RAM用户)的 accesskey id和secret
* YOUR APP_KEY : 写入自己的 appkey
*/
public function ajaxAfsCheck(Request $request)
{
if ($request->isPost()) {
$postData = $request->post();
include_once '../extend/aliyun/aliyun-php-sdk-core/Config.php';
$iClientProfile = \DefaultProfile::getProfile("cn-hangzhou", "YOUR ACCESS_KEY",
"YOUR ACCESS_SECRET");
$client = new \DefaultAcsClient($iClientProfile);
\DefaultProfile::addEndpoint("cn-hangzhou", "cn-hangzhou", "afs", "afs.aliyuncs.com");
$request = new Afs\AuthenticateSigRequest();
$ip = get_real_ips(); //自定义的一个获取IP地址的方法
$request->setSessionId($postData["csessionid"]);// 必填参数,从前端获取,不可更改,android和ios只传这个参数即可
$request->setToken($postData['token']);// 必填参数,从前端获取,不可更改
$request->setSig($postData['sig']);// 必填参数,从前端获取,不可更改
$request->setScene('nc_login');// 必填参数,从前端获取,不可更改
$request->setAppKey("YOUR APP_KEY");//必填参数,后端填写(写入自己的 appkey)
$request->setRemoteIp($ip);//必填参数,后端填写
$response = $client->getAcsResponse($request);//返回code 100表示验签通过,900表示验签失败
$opTag = ($response->Code === 100) ? 1 : 0;
$message = ($response->Code === 100)? "验签通过":"验签失败";
if ($opTag){
Session::set('NC_TOKEN',$postData['token']);
}else{
Session::set('NC_TOKEN','NULL');
}
} else {
$opTag = 0;
$message = "请求不合法";
}
return showMsg($opTag, $message,$response); //就是返回 json_encode()处理后的数据
}
㈣ 后期处理以及效果
在前面的操作完成后,按照完整的业务处理逻辑,紧接着就是要处理登录按钮的触发事件了
> 鄙人的操作是:
在登录按钮触发的 ajax 请求验证中;
判断当前 Session 中的 "NC_TOKEN " 是否和 前端隐藏域传来的 "nc_token" 值相等 ;
如果相等,说明已成功滑动验证通过,继而判断账号和密码是否能成功登录;
反之提示刷新再次进行验证 ...
-
执行效果图:
附录:
- 频繁查看的链接:【
云盾·人机控制台
】 - 一方面觉得写得太详细了,有点显得冗杂了,其实看文档仔细点也是没问题的
提示:多留意一下,我在"㈠ 前期准备"
中提及的信息,尤为重要!! - 补充,后台获取IP 地址的函数:
/**
* 此方法返回用户的IP地址,同时如果拥有代理IP,将会以逗号追加在后面
* 如果只取用当前IP,可参考 :
* $ips = explode(',', $bargainModel->get_real_ips());
* $ip = $ips[0];
*/
function get_real_ips()
{
global $ip;
if (getenv("HTTP_CLIENT_IP")) {
$ip = getenv("HTTP_CLIENT_IP");
} else if (getenv("HTTP_X_FORWARDED_FOR")) {
$ip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("REMOTE_ADDR")) {
$ip = getenv("REMOTE_ADDR");
} else {
$ip = "NULL";
}
return $ip;
}