feat: 滑块验证码增加服务器端验证
This commit is contained in:
parent
1b7fec25e4
commit
17914936dc
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Bootstrap.Client.Controllers.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gitee 网站信息接口类
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class CaptchaController : ControllerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 服务器端滑块验证方法
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public bool Post([FromBody]List<int> datas)
|
||||||
|
{
|
||||||
|
var sum = datas.Sum();
|
||||||
|
var avg = sum * 1.0 / datas.Count;
|
||||||
|
var stddev = datas.Select(v => Math.Pow(v - avg, 2)).Sum() / datas.Count;
|
||||||
|
return stddev != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,8 @@
|
||||||
that.sliderCaptcha('reset');
|
that.sliderCaptcha('reset');
|
||||||
$('.userinfo .dropdown-menu a:first')[0].click();
|
$('.userinfo .dropdown-menu a:first')[0].click();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
},
|
||||||
|
remoteUrl: $.formatUrl('api/Captcha')
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#btnCaptcha').on('click', function () {
|
$('#btnCaptcha').on('click', function () {
|
||||||
|
|
|
@ -24,7 +24,24 @@
|
||||||
maxLoadCount: 3,
|
maxLoadCount: 3,
|
||||||
localImages: function () {
|
localImages: function () {
|
||||||
return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
return 'images/Pic' + Math.round(Math.random() * 4) + '.jpg';
|
||||||
}
|
},
|
||||||
|
verify: function (arr, url) {
|
||||||
|
var ret = false;
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
data: JSON.stringify(arr),
|
||||||
|
async: false,
|
||||||
|
cache: false,
|
||||||
|
type: 'POST',
|
||||||
|
contentType: 'application/json',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (result) {
|
||||||
|
ret = result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
remoteUrl: null
|
||||||
};
|
};
|
||||||
|
|
||||||
function Plugin(option) {
|
function Plugin(option) {
|
||||||
|
@ -273,16 +290,23 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.verify = function () {
|
_proto.verify = function () {
|
||||||
var sum = function (x, y) { return x + y; };
|
|
||||||
var square = function (x) { return x * x; };
|
|
||||||
var arr = this.trail; // 拖动时y轴的移动距离
|
var arr = this.trail; // 拖动时y轴的移动距离
|
||||||
var average = arr.reduce(sum) / arr.length;
|
|
||||||
var deviations = arr.map(function (x) { return x - average; });
|
|
||||||
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
|
|
||||||
var left = parseInt(this.block.style.left);
|
var left = parseInt(this.block.style.left);
|
||||||
|
var verified = false;
|
||||||
|
if (this.options.remoteUrl !== null) {
|
||||||
|
verified = this.options.verify(arr, this.options.remoteUrl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var sum = function (x, y) { return x + y; };
|
||||||
|
var square = function (x) { return x * x; };
|
||||||
|
var average = arr.reduce(sum) / arr.length;
|
||||||
|
var deviations = arr.map(function (x) { return x - average; });
|
||||||
|
var stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length);
|
||||||
|
verified = stddev !== 0;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
spliced: Math.abs(left - this.x) < this.options.offset,
|
spliced: Math.abs(left - this.x) < this.options.offset,
|
||||||
verified: stddev !== 0 // 简单验证下拖动轨迹,为零时表示Y轴上下没有波动,可能非人为操作
|
verified: verified
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,131 +1,131 @@
|
||||||
body {
|
body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer {
|
.sliderContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
background: #f7f9fa;
|
background: #f7f9fa;
|
||||||
color: #45494c;
|
color: #45494c;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderbg {
|
.sliderbg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: #f7f9fa;
|
background-color: #f7f9fa;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid #e6e8eb;
|
border: 1px solid #e6e8eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_active .slider {
|
.sliderContainer_active .slider {
|
||||||
top: -1px;
|
top: -1px;
|
||||||
border: 1px solid #1991FA;
|
border: 1px solid #1991FA;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_active .sliderMask {
|
.sliderContainer_active .sliderMask {
|
||||||
border-width: 1px 0 1px 1px;
|
border-width: 1px 0 1px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_success .slider {
|
.sliderContainer_success .slider {
|
||||||
top: -1px;
|
top: -1px;
|
||||||
border: 1px solid #52CCBA;
|
border: 1px solid #52CCBA;
|
||||||
background-color: #52CCBA !important;
|
background-color: #52CCBA !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_success .sliderMask {
|
.sliderContainer_success .sliderMask {
|
||||||
border: 1px solid #52CCBA;
|
border: 1px solid #52CCBA;
|
||||||
border-width: 1px 0 1px 1px;
|
border-width: 1px 0 1px 1px;
|
||||||
background-color: #D2F4EF;
|
background-color: #D2F4EF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_success .sliderIcon:before {
|
.sliderContainer_success .sliderIcon:before {
|
||||||
content: "\f00c";
|
content: "\f00c";
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_fail .slider {
|
.sliderContainer_fail .slider {
|
||||||
top: -1px;
|
top: -1px;
|
||||||
border: 1px solid #f57a7a;
|
border: 1px solid #f57a7a;
|
||||||
background-color: #f57a7a !important;
|
background-color: #f57a7a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_fail .sliderMask {
|
.sliderContainer_fail .sliderMask {
|
||||||
border: 1px solid #f57a7a;
|
border: 1px solid #f57a7a;
|
||||||
background-color: #fce1e1;
|
background-color: #fce1e1;
|
||||||
border-width: 1px 0 1px 1px;
|
border-width: 1px 0 1px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_fail .sliderIcon:before {
|
.sliderContainer_fail .sliderIcon:before {
|
||||||
content: "\f00d";
|
content: "\f00d";
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {
|
.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderMask {
|
.sliderMask {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border: 0 solid #1991FA;
|
border: 0 solid #1991FA;
|
||||||
background: #D1E9FE;
|
background: #D1E9FE;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider {
|
.slider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .2s linear;
|
transition: background .2s linear;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider:hover {
|
.slider:hover {
|
||||||
background: #1991FA;
|
background: #1991FA;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider:hover .sliderIcon {
|
.slider:hover .sliderIcon {
|
||||||
background-position: 0 -13px;
|
background-position: 0 -13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderText {
|
.sliderText {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderIcon {
|
.sliderIcon {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.refreshIcon {
|
.refreshIcon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 6px;
|
margin: 6px;
|
||||||
color: rgba(0,0,0,.25);
|
color: rgba(0,0,0,.25);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
transition: color .3s linear;
|
transition: color .3s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.refreshIcon:hover {
|
.refreshIcon:hover {
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue