许多网站为了防止注册或者登入界面被人盗刷,会有很多校验,一般很多人会用到验证码,种类很多
1:数字验证码
2:图片验证码
3:短信验证码
4:邮件验证 等等
其实目的都是一样,防止接口被人攻击,这里我用图片验证码做一下实例说明。接口用的是网易的,需要收费
效果都清楚了,现在关键是如何实现功能:
第一,需要引用网易的js
@*网易云盾*@
第二:添加 Html按钮
@*start20191015 新增手机验证码*@
@*end*@
第三:添加关联js:
// 网易云盾 初始化方法
var captchaIns;
initNECaptcha({
element: '#captcha',
captchaId: '663464f032c94867677fb676b49bd66', // 这个是假的,这个是需要付费的
mode: 'popup',
width: '320px',
onVerify: function (err, data) {
if (err != undefined ||data == undefined ||data.validate == undefined) {
$.fn.showAlert("@Html.Lang("Account_0101")");
return;
}
if (!err) {
SendSMSLoginCode();
captchaIns.refresh();
}
}
}, function (instance) {
captchaIns = instance
}, function (err) { });
$("#btnAuthCodeL").click(function () {
var phoneNo = $.trim($("#Contact").val());
if (!phoneNo.isMobile()) {
$.fn.showAlert("@Html.Lang("UserCenter_0014")");
$("#Contact").focus();
return;
}
var _code = $("input[name='NECaptchaValidate']").val();
if (_code == "" || _code.length == 0) {
captchaIns && captchaIns.popUp()
return;
}
});
//发送验证码
function SendSMSLoginCode() {
var phoneNo = $.trim($("#Contact").val());
var _code = $("input[name='NECaptchaValidate']").val();
$.ajax({
url: '@Url.Action("YdSMSLoginCode", "Account")',
data: {
mobile: phoneNo,
NECaptchaValidate: _code
},
dataType: 'Json',
type: 'Post',
success: function (data) {
if (data.result) {
$("#btnAuthCodeL").attr("disabled", "disabled");
$.fn.showAlert(AnyOneQueryOrder_VerificationCodeSended + phoneNo + AnyOneQueryOrder_NoteToReceive);
// 进行修改 按钮文字
setCodeButtonText();
$("#qyzm").attr("readonly", "readonly"); //禁用验证码框
} else {
$.fn.showAlert(data.message);
captchaIns && captchaIns.refresh();
}
},
error: function () {
$.fn.showAlert(ServerExceptional_Const);
captchaIns && captchaIns.refresh();
}
});
}
var flagTime = 180;
function setCodeButtonText() {
if (flagTime > 0) {
flagTime--;
$("#btnAuthCodeL").val(AnyOneQueryOrder_Remainder + flagTime + AnyOneQueryOrder_Second);
id_of_setinterval = setTimeout(setCodeButtonText, 1000);
$("#btnAuthCodeL").attr("title", AnyOneQueryOrder_Remainder + flagTime + AnyOneQueryOrder_Second);
} else {
flagTime = 180;
clearTimeout(id_of_setinterval);
$("#btnAuthCodeL").removeAttr("disabled");
$("#btnAuthCodeL").val(AnyOneQueryOrder_GetVerificationCode);
$("#btnAuthCodeL").attr("title", '@Html.Lang("Account_fcode")');
$("#qyzm").removeAttr("readonly");//取消验证码的只读
$("#imgCode1").removeAttr("disabled");//取消验证码图片点击
$("#imgCode1").bind("click", function () { flush('imgCode1'); });
flush('imgCode1');//刷新验证码
}
}
第四:控制器后台代码逻辑实现
///
/// 快捷登录时获取短信验证码 易盾验证码获取
/// Create by suhua
///
///
public ActionResult YdSMSLoginCode(string mobile, string NECaptchaValidate)
{
if (String.IsNullOrEmpty(mobile) || String.IsNullOrEmpty(NECaptchaValidate))
{
return Json(new { Result = false, Message = "请求参数错误" });
}
#region 网易云盾验证 update by suhua 20180516
string apiUrl = ConfigCenterValue.Instance.NetEaseDunApiUrl; //易盾url
string captchaId = ConfigCenterValue.Instance.NetEaseDunCaptchaId; //易盾captchaId
string secretId = ConfigCenterValue.Instance.NetEaseDunSecretId; //易盾secretId
string secretKey = ConfigCenterValue.Instance.NetEaseDunSecretKey; //易盾secretKey
NECaptchaVerifier verifier = new NECaptchaVerifier(apiUrl, captchaId, new NESecretPair(secretId, secretKey));
bool verifyResult = verifier.verify(NECaptchaValidate, null);
if (!verifyResult)
{
return Json(new { Result = false, Message = LocalizationConfig.langInner(this.HttpContext, "Account_0083") });
}
#endregion
}
第五:后台校验网易云的验证是否正确:
//
/// 易盾验证码二次校验接口简单封装demo
///
public class NECaptchaVerifier
{
public static string REQ_VALIDATE = "NECaptchaValidate"; // 二次验证带过来的validate
private string apiUrl = string.Empty;//接口地址
private string captchaId; // 验证码id
private NESecretPair secretPair; // 密钥对
private readonly string VERSION = "v2";
private readonly HttpClient client = Utils.makeHttpClient();
public NECaptchaVerifier(string apiUrl, string captchaId, NESecretPair secretPair)
{
this.captchaId = captchaId;
this.secretPair = secretPair;
this.apiUrl = apiUrl;
}
///
/// 向易盾验证码后台发起二次校验请求
///
/// 二次校验请求字符串
/// 当前用户信息,可以为空字符串
///
public bool verify(string validate, string user)
{
if (String.IsNullOrEmpty(validate))
{
return false;
}
user = (user == null) ? "" : user;
Dictionary
long curr = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
String time = curr.ToString();
parameters.Add("captchaId", captchaId);
parameters.Add("validate", validate);
parameters.Add("user", user);
// 1.设置公共参数
parameters.Add("secretId", secretPair.secretId);
parameters.Add("version", VERSION);
parameters.Add("timestamp", time);
parameters.Add("nonce", new Random().Next().ToString());
// 2.生成签名信息
String signature = Utils.genSignature(secretPair.secretKey, parameters);
parameters.Add("signature", signature);
// 3.发送HTTP请求
String response = Utils.doPost(client, apiUrl, parameters, 5000);
return verifyRet(response);
}
///
/// 解析二次校验接口返回的结果
///
///
///
private bool verifyRet(string response)
{
if (String.IsNullOrEmpty(response))
{
AppLog.Write("网易云盾验证失败:无返回值", LogMessageType.Warn);
return false;
}
try
{
JObject j = JObject.Parse(response);
JToken jToken;
j.TryGetValue("result", out jToken);
bool isOk = jToken.ToObject
if (!isOk)
AppLog.Write(string.Format("网易云盾验证失败:{0}", response), LogMessageType.Warn);
return isOk;
}
catch (Exception e)
{
AppLog.Write(string.Format("网易云盾验证失败:{0}/{1}", response, e.ToString()), LogMessageType.Error);
}
return false;
}
}
///
/// 易盾验证码密钥对
///
public class NESecretPair
{
public string secretId; // 密钥对id
public string secretKey; // 密钥对key
public NESecretPair(string secretId, string secretKey)
{
this.secretId = secretId;
this.secretKey = secretKey;
}
}
第六: Utils类的方法
public class Utils
{
///
/// 根据请求参数生成对应的签名信息
///
///
///
///
public static String genSignature(String secretKey, Dictionary
{
parameters = parameters.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value);
StringBuilder builder = new StringBuilder();
foreach (KeyValuePair
{
builder.Append(kv.Key).Append(kv.Value);
}
builder.Append(secretKey);
String tmp = builder.ToString();
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(tmp));
builder.Clear();
foreach (byte b in result)
{
builder.Append(b.ToString("x2").ToLower());
}
return builder.ToString();
}
public static HttpClient makeHttpClient()
{
HttpClient client = new HttpClient() { };
client.DefaultRequestHeaders.Connection.Add("keep-alive");
return client;
}
///
/// 发起HTTP-Post请求
///
/// httpClient对象
/// 请求接口url
/// 请求参数
/// 超时时间
///
public static String doPost(HttpClient client, String url, Dictionary
{
try
{
HttpContent content = new FormUrlEncodedContent(parameters);
Task
if (task.Wait(timeOutInMillisecond))
{
HttpResponseMessage response = task.Result;
if (response.StatusCode == HttpStatusCode.OK)
{
Task
result.Wait();
return result.Result;
}
}
}
catch (Exception ex)
{
AppLog.Write(string.Format("网易云盾验证码异常:{0}", ex.ToString()), LogMessageType.Error);
}
return null;
}
}