vue2.0+.net core 实现极验验证
最近看滑动验证码挺火的,所以就想自己去实验做一下效果。
1.去官网申请id和key,注册进入后台
http://www.geetest.com/
2.配置前端页面
2.1下载js
1 /* initGeetest 1.0.0
2 * 用于加载id对应的验证码库,并支持宕机模式
3 * 暴露 initGeetest 进行验证码的初始化
4 * 一般不需要用户进行修改
5 */
6 var gtInit =(function (global, factory) {
7 "use strict";
8 if (typeof module === "object" && typeof module.exports === "object") {
9 // CommonJS
10 module.exports = global.document ?
11 factory(global, true) :
12 function (w) {
13 if (!w.document) {
14 throw new Error("Geetest requires a window with a document");
15 }
16 return factory(w);
17 };
18 } else {
19 factory(global);
20 }
21 })(typeof window !== "undefined" ? window : this, function (window, noGlobal) {
22 "use strict";
23 if (typeof window === 'undefined') {
24 throw new Error('Geetest requires browser environment');
25 }
26 var document = window.document;
27 var Math = window.Math;
28 var head = document.getElementsByTagName("head")[0];
29
30 function _Object(obj) {
31 this._obj = obj;
32 }
33
34 _Object.prototype = {
35 _each: function (process) {
36 var _obj = this._obj;
37 for (var k in _obj) {
38 if (_obj.hasOwnProperty(k)) {
39 process(k, _obj[k]);
40 }
41 }
42 return this;
43 }
44 };
45 function Config(config) {
46 var self = this;
47 new _Object(config)._each(function (key, value) {
48 self[key] = value;
49 });
50 }
51
52 Config.prototype = {
53 api_server: 'api.geetest.com',
54 protocol: 'http://',
55 type_path: '/gettype.php',
56 fallback_config: {
57 slide: {
58 static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
59 type: 'slide',
60 slide: '/static/js/geetest.0.0.0.js'
61 },
62 fullpage: {
63 static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"],
64 type: 'fullpage',
65 fullpage: '/static/js/fullpage.0.0.0.js'
66 }
67 },
68 _get_fallback_config: function () {
69 var self = this;
70 if (isString(self.type)) {
71 return self.fallback_config[self.type];
72 } else if (self.new_captcha) {
73 return self.fallback_config.fullpage;
74 } else {
75 return self.fallback_config.slide;
76 }
77 },
78 _extend: function (obj) {
79 var self = this;
80 new _Object(obj)._each(function (key, value) {
81 self[key] = value;
82 })
83 }
84 };
85 var isNumber = function (value) {
86 return (typeof value === 'number');
87 };
88 var isString = function (value) {
89 return (typeof value === 'string');
90 };
91 var isBoolean = function (value) {
92 return (typeof value === 'boolean');
93 };
94 var isObject = function (value) {
95 return (typeof value === 'object' && value !== null);
96 };
97 var isFunction = function (value) {
98 return (typeof value === 'function');
99 };
100 var callbacks = {};
101 var status = {};
102 var random = function () {
103 return parseInt(Math.random() * 10000) + (new Date()).valueOf();
104 };
105 var loadScript = function (url, cb) {
106 var script = document.createElement("script");
107 script.charset = "UTF-8";
108 script.async = true;
109 script.onerror = function () {
110 cb(true);
111 };
112 var loaded = false;
113 script.onload = script.onreadystatechange = function () {
114 if (!loaded &&
115 (!script.readyState ||
116 "loaded" === script.readyState ||
117 "complete" === script.readyState)) {
118
119 loaded = true;
120 setTimeout(function () {
121 cb(false);
122 }, 0);
123 }
124 };
125 script.src = url;
126 head.appendChild(script);
127 };
128 var normalizeDomain = function (domain) {
129 return domain.replace(/^https?:\/\/|\/$/g, '');
130 };
131 var normalizePath = function (path) {
132 path = path.replace(/\/+/g, '/');
133 if (path.indexOf('/') !== 0) {
134 path = '/' + path;
135 }
136 return path;
137 };
138 var normalizeQuery = function (query) {
139 if (!query) {
140 return '';
141 }
142 var q = '?';
143 new _Object(query)._each(function (key, value) {
144 if (isString(value) || isNumber(value) || isBoolean(value)) {
145 q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
146 }
147 });
148 if (q === '?') {
149 q = '';
150 }
151 return q.replace(/&$/, '');
152 };
153 var makeURL = function (protocol, domain, path, query) {
154 domain = normalizeDomain(domain);
155
156 var url = normalizePath(path) + normalizeQuery(query);
157 if (domain) {
158 url = protocol + domain + url;
159 }
160
161 return url;
162 };
163 var load = function (protocol, domains, path, query, cb) {
164 var tryRequest = function (at) {
165
166 var url = makeURL(protocol, domains[at], path, query);
167 loadScript(url, function (err) {
168 if (err) {
169 if (at >= domains.length - 1) {
170 cb(true);
171 } else {
172 tryRequest(at + 1);
173 }
174 } else {
175 cb(false);
176 }
177 });
178 };
179 tryRequest(0);
180 };
181 var jsonp = function (domains, path, config, callback) {
182 if (isObject(config.getLib)) {
183 config._extend(config.getLib);
184 callback(config);
185 return;
186 }
187 if (config.offline) {
188 callback(config._get_fallback_config());
189 return;
190 }
191 var cb = "geetest_" + random();
192 window[cb] = function (data) {
193 if (data.status === 'success') {
194 callback(data.data);
195 } else if (!data.status) {
196 callback(data);
197 } else {
198 callback(config._get_fallback_config());
199 }
200 window[cb] = undefined;
201 try {
202 delete window[cb];
203 } catch (e) {
204 }
205 };
206 load(config.protocol, domains, path, {
207 gt: config.gt,
208 callback: cb
209 }, function (err) {
210 if (err) {
211 callback(config._get_fallback_config());
212 }
213 });
214 };
215 var throwError = function (errorType, config) {
216 var errors = {
217 networkError: '网络错误'
218 };
219 if (typeof config.onError === 'function') {
220 config.onError(errors[errorType]);
221 } else {
222 throw new Error(errors[errorType]);
223 }
224 };
225 var detect = function () {
226 return !!window.Geetest;
227 };
228 if (detect()) {
229 status.slide = "loaded";
230 }
231 var initGeetest = function (userConfig, callback) {
232 var config = new Config(userConfig);
233 if (userConfig.https) {
234 config.protocol = 'https://';
235 } else if (!userConfig.protocol) {
236 config.protocol = window.location.protocol + '//';
237 }
238 jsonp([config.api_server || config.apiserver], config.type_path, config, function (newConfig) {
239 var type = newConfig.type;
240 var init = function () {
241 config._extend(newConfig);
242 callback(new window.Geetest(config));
243 };
244 callbacks[type] = callbacks[type] || [];
245 var s = status[type] || 'init';
246 if (s === 'init') {
247 status[type] = 'loading';
248 callbacks[type].push(init);
249 load(config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {
250 if (err) {
251 status[type] = 'fail';
252 throwError('networkError', config);
253 } else {
254 status[type] = 'loaded';
255 var cbs = callbacks[type];
256 for (var i = 0, len = cbs.length; i < len; i = i + 1) {
257 var cb = cbs[i];
258 if (isFunction(cb)) {
259 cb();
260 }
261 }
262 callbacks[type] = [];
263 }
264 });
265 } else if (s === "loaded") {
266 init();
267 } else if (s === "fail") {
268 throwError('networkError', config);
269 } else if (s === "loading") {
270 callbacks[type].push(init);
271 }
272 });
273 };
274 window.initGeetest = initGeetest;
275 return initGeetest;
276 });
277
278 export default {
279 gtInit
280 }
View Code
2.2然后进行引用
显示验证码的地方 <el-form-item> <div id="captcha"></div> <el-alert id="wait" class="show" title="正在加载验证码......" type="success"> </el-alert> </el-form-item> import gtInit from '../common/js/gt' 定义三个参数用来后续传到服务器进行验证 geetest_challenge:'', geetest_validate:'', geetest_seccode:'', 2.3定义一个方法用来初始化
1 handleInit(){
2 let _this=this;
3 api.getCaptcha().then(res => {
4 let { msg, code, data } = res;
5 window.initGeetest({
6 gt: data.gt,
7 challenge: data.challenge,
8 width:"340px",
9 product: "embed", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
10 offline: !data.success, // 表示用户后台检测极验服务器是否宕机,一般不需要关注
11 new_captcha: data.new_captcha
12 }, function(catchaObj){
13 catchaObj.appendTo("#captcha");
14 catchaObj.onReady(function(){
15 document.getElementById('wait').style.display='none';
16 });
17 catchaObj.onSuccess(function(){
18 _this.geetest_challenge=document.getElementsByTagName('input')['geetest_challenge'].value;
19 _this.geetest_validate=document.getElementsByTagName('input')['geetest_validate'].value;
20 _this.geetest_seccode=document.getElementsByTagName('input')['geetest_seccode'].value;
21 });
22 catchaObj.onError(function(){
23 console.log('出错啦,请稍后重试');
24 })
25 })
26 });
27 },
View Code api.getCaptcha()调用的接口 API.get('/login/getCaptcha?t='+(new Date()).getTime(), params)
2.4调用
created(){ this.handleInit(); } 服务器控制器接口
1 [Route("login")]
2 public class LoginController: ApiController
3 {
4 private IOptions<RecordAccountGeetestOption> _geetestOptions;
5 private ILoggerFactory _loggerFactory;
6 private readonly ILoginService _loginService;
7 public LoginController(ILoginService loginService, IOptions<RecordAccountGeetestOption> geetestOptions, ILoggerFactory loggerFactory)
8 {
9 _loginService = loginService;
10 _geetestOptions = geetestOptions;
11 _loggerFactory = loggerFactory;
12 }
13
14 /// <summary>
15 ///用户登陆
16 /// </summary>
17 /// <returns></returns>
18 [HttpPost, Route("index")]
19 [NoToken]
20 [ProducesResponseType(typeof(ResponseObjectExtension.ResponseObject<bool>), (int)HttpStatusCode.OK)]
21 public async Task<HttpResponseMessage> IndexAsync([FromBody]LoginRequestDto req)
22 {
23 var validateCode = await ValidateCaptcha(req.GeetestChallenge, req.GeetestValidate, req.GeetestSeccode);
24 if (validateCode == 1)
25 {
26 var user = await _loginService.LoginValidateAsync(req);
27 if (user != null)
28 {
29 var userSession = new CurrentUser
30 {
31 Id = user.Id,
32 Name = user.UserName
33 };
34 var token = Guid.NewGuid().ToString("N");
35 RedisHelper.Set(token, userSession, TimeSpan.FromMinutes(60));
36 return this.Success(token);
37 }
38 return this.Error(ErrCodeCommon.LoginError);
39 }
40 else
41 return this.Error(ErrCodeCommon.ValidateCodeErr);
42 }
43
44 /// <summary>
45 /// 二次进行验证码验证
46 /// </summary>
47 /// <param name="geetestChallenge">本次验证会话的唯一标识</param>
48 /// <param name="geetestValidate">拖动完成后server端返回的验证结果标识字符串</param>
49 /// <param name="geetestSeccode">验证结果的校验码,如果gt-server返回的不与这个值相等则表明验证失败</param>
50 /// <returns></returns>
51 public async Task<int> ValidateCaptcha(string geetestChallenge,string geetestValidate,string geetestSeccode)
52 {
53 GeetestLib geetest = new GeetestLib(_geetestOptions, _loggerFactory);
54 Byte gt_server_status_code = RedisHelper.Get<Byte>(GeetestLib.gtServerStatusSessionKey);
55 string userID = RedisHelper.Get("captchaUserID").ToString();
56 string challenge = geetestChallenge;
57 string validate =geetestValidate;
58 string seccode = geetestSeccode;
59 int res = 0;
60 if (gt_server_status_code == 1)
61 res = await geetest.enhencedValidateRequest(challenge, validate, seccode, userID);
62 else
63 res = geetest.failbackValidateRequest(challenge, validate, seccode);
64 return res;
65 }
66 /// <summary>
67 /// 获取验证码
68 /// </summary>
69 /// <returns></returns>
70 [HttpGet, Route("getCaptcha")]
71 public async Task<HttpResponseMessage> getCaptcha()
72 {
73 GeetestLib geetest = new GeetestLib(_geetestOptions, _loggerFactory);
74 string userID = Guid.NewGuid().ToString("N");
75 //验证初始化预处理 判断极验服务器是否宕机
76 Byte gtServerStatus = await geetest.preProcess(userID, "web", _geetestOptions.Value.IpAddress);
77 //进行存储
78 RedisHelper.Set("captchaUserID", userID, TimeSpan.FromMinutes(3));
79 RedisHelper.Set(GeetestLib.gtServerStatusSessionKey, gtServerStatus, TimeSpan.FromMinutes(3));
80 return this.Success(JsonConvert.DeserializeObject<GeetestResponseHelper>(geetest.getResponseStr()));
81 }
82 }
View Code
下面的是涉及到的一些实体和注册
public class RecordAccountGeetestOption: GeetestOptions
{
public string IpAddress { get; set; }
}
在startUp.cs注册
services.Configure<RecordAccountGeetestOption>(Configuration.GetSection(nameof(RecordAccountGeetestOption)));
appsettings.json
"RecordAccountGeetestOption": {
"Id": "",
"Key": "",
"IpAddress": "localhost"
},
posted on 2018-09-18 16:59 chen123gang 阅读( ...) 评论( ...) 编辑 收藏
转载于:https://www.cnblogs.com/cg-931210/p/9669944.html