UNPKG

geetest

Version:
222 lines (189 loc) 6.51 kB
"use strict"; var crypto = require('crypto'), request = require('request'), pkg = require("./package.json"); var md5 = function (str) { return crypto.createHash('md5').update(String(str)).digest('hex'); }; var randint = function (from, to) { // range: from ~ to return Math.floor(Math.random() * (to - from + 1) + from); }; function Geetest(config) { if (!config.geetest_id) { throw new Error('Geetest ID Required'); } if (!config.geetest_key) { throw new Error("Geetest KEY Required"); } if (config.protocol) { this.PROTOCOL = config.protocol; } if (config.api_server) { this.API_SERVER = config.api_server; } this.geetest_id = config.geetest_id; this.geetest_key = config.geetest_key; } Geetest.prototype = { PROTOCOL: 'http://', API_SERVER: 'api.geetest.com', VALIDATE_PATH: '/validate.php', REGISTER_PATH: '/register.php', validate: function (result, callback) { var that = this; return new Promise(function (resolve, reject) { that._validate(result, function (err, data) { if (typeof callback === 'function') { callback(err, data); } if (err) { reject(err); } else { resolve(data); } }); }) }, _validate: function (result, callback) { var challenge = result.challenge; var validate = result.validate; if (validate.split('_').length === 3) { var validate_strs = validate.split('_'); var encode_ans = validate_strs[0]; var encode_fbii = validate_strs[1]; var encode_igi = validate_strs[2]; var decode_ans = this._decode_response(challenge, encode_ans); var decode_fbii = this._decode_response(challenge, encode_fbii); var decode_igi = this._decode_response(challenge, encode_igi); var validate_result = this._validate_fail_image(decode_ans, decode_fbii, decode_igi); if (validate_result === 1) { callback(null, true); } else { callback(null, false); } } else { var hash = this.geetest_key + 'geetest' + result.challenge; if (result.validate === md5(hash)) { var url = this.PROTOCOL + this.API_SERVER + this.VALIDATE_PATH; request.post(url, { form: { seccode: result.seccode } }, function (err, res, body) { if (err) { callback(err); } else { callback(null, body === md5(result.seccode)); } }); } else { callback(null, false); } } }, _validate_fail_image: function (ans, full_bg_index, img_grp_index) { var thread = 3; var full_bg_name = md5(full_bg_index).slice(0, 10); var bg_name = md5(img_grp_index).slice(10, 20); var answer_decode = ''; var i; for (i = 0; i < 9; i = i + 1) { if (i % 2 == 0) { answer_decode += full_bg_name[i]; } else { answer_decode += bg_name[i]; } } var x_decode = answer_decode.slice(4); var x_int = parseInt(x_decode, 16); var result = x_int % 200; if (result < 40) { result = 40; } if (Math.abs(ans - result) < thread) { return 1; } else { return 0; } }, _decode_response: function (challenge, userresponse) { if (userresponse.length > 100) { return 0; } var shuzi = [1, 2, 5, 10, 50]; var chongfu = []; var key = {}; var count = 0, i, len; for (i = 0, len = challenge.length; i < len; i = i + 1) { var c = challenge[i]; if (chongfu.indexOf(c) === -1) { chongfu.push(c); key[c] = shuzi[count % 5]; count += 1; } } var res = 0; for (i = 0, len = userresponse.length; i < len; i = i + 1) { res += key[userresponse[i]] || 0; } res = res - this._decode_rand_base(challenge); return res; }, _decode_rand_base: function (challenge) { var str_base = challenge.slice(32); var i, len, temp_array = []; for (i = 0, len = str_base.length; i < len; i = i + 1) { var temp_char = str_base[i]; var temp_ascii = temp_char.charCodeAt(0); var result = temp_ascii > 57 ? temp_ascii - 87 : temp_ascii - 48; temp_array.push(result); } var decode_res = temp_array[0] * 36 + temp_array[1]; return decode_res; }, register: function (callback) { var that = this; return new Promise(function (resolve, reject) { that._register(function (err, data) { if (typeof callback === 'function') { callback(err, data); } if (err) { reject(err); } else { resolve(data); } }); }); }, _register: function (callback) { var url = this.PROTOCOL + this.API_SERVER + this.REGISTER_PATH + '?gt=' + this.geetest_id + '&sdk=Node_' + pkg.version; var that = this; request.get(url, {timeout: 2000}, function (err, res, challenge) { if (err || challenge.length !== 32) { // fallback callback(null, { success: 0, challenge: that._make_challenge(), gt: that.geetest_id }); } else { callback(null, { success: 1, challenge: md5(challenge + that.geetest_key), gt: that.geetest_id }); } }); }, _make_challenge: function () { var rnd1 = randint(0, 90); var rnd2 = randint(0, 90); var md5_str1 = md5(rnd1); var md5_str2 = md5(rnd2); return md5_str1 + md5_str2.slice(0, 2); } }; module.exports = Geetest;