【发布时间】:2021-03-18 17:33:08
【问题描述】:
我已经在我的 .Net MVC Web 应用程序中构建了一个基于 Ajax 的表单,但我无法停止被黑客攻击并被用来向我发送垃圾邮件。
@using (Ajax.BeginForm("ContactSend", "Home", null, new AjaxOptions { OnBegin = "Contact.submitOnBegin", OnSuccess = "Contact.submitOnSuccess" }, new { id = "contact-form" }))
{
@Html.AntiForgeryToken()
<input id="contact-cta" type="hidden" name="cta" value="@ViewBag.CTA" />
<label class="form-label" for="nome">@Resources.Contact_Form_Name <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-name" type="text" name="name">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
<label class="form-label" for="email">@Resources.Contact_Form_Email <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-email" type="text" name="email">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
<div class="invalid-error">@Resources.Contact_Form_Invalid</div>
</div>
<label class="form-label" for="phone">@Resources.Contact_Form_Phone <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<input id="contact-phone" type="text" name="phone">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
<div class="invalid-error">@Resources.Contact_Form_Invalid</div>
</div>
if (!string.IsNullOrEmpty(ViewBag.Subject))
{
<label class="form-label" for="subject">@Resources.Contact_Form_Subject</label>
<div class="form-input-ctn">
<input id="contact-subject" type="text" name="subject" value="@ViewBag.Subject">
<div class="mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
}
<label class="form-label" for="message">@Resources.Contact_Form_Message <span class="mandatory">*</span></label>
<div class="form-input-ctn">
<textarea id="contact-message" class="form-textarea" name="message">@ViewBag.Message</textarea>
<div class="mandatory-error message-mandatory-error">@Resources.Contact_Form_Mandatory</div>
</div>
<label class="form-label"><span class="mandatory">*</span> @Resources.Contact_Form_Mandatory</label>
<div class="form-input-ctn">
<div id="contact-recaptcha-mandatory-error" class="recaptcha-mandatory">@Resources.Contact_Form_Mandatory</div>
<div id="contact-recaptcha" class="g-recaptcha" data-callback="reCaptchaOnValidCallback"></div>
</div>
<br />
<input id="contact-submit-btn" class="form-submit" type="submit" value="@Resources.Contact_Form_Send_Button" data-sending-message="@Resources.Contact_Form_Sending_Button">
}
我还加入了 Google reCaptcha,但没有任何改变。
在我的 Contact.submitOnBegin jQuery 代码中,我进行了所有验证以避免空白值和无效值:
var _submitOnBegin = function () {
_isFormValid();
if (isFormValid) {
$submitBtn.prop('disabled', true);
var sendingMessage = $submitBtn.data("sending-message");
$submitBtn.addClass("submitting");
$submitBtn.val(sendingMessage);
} else {
return false;
}
};
在 isFormValid 函数中,我对每个输入进行所有测试:
var _isFormValid = function () {
// Reset
isFocusOn = false;
isFormValid = true;
// Name
if ($contactName.val() == "") {
_showErrorMessage($contactName, contactErrorMandatoryCls);
}
// Email
if ($contactEmail.val() == "") {
_showErrorMessage($contactEmail, contactErrorMandatoryCls);
}
else if (!_isEmailValid()) {
_showErrorMessage($contactEmail, contactErrorInvalidCls);
}
// Phone
if ($contactPhone.val() == "") {
_showErrorMessage($contactPhone, contactErrorMandatoryCls);
}
else if (!_isPhoneValid()) {
_showErrorMessage($contactPhone, contactErrorInvalidCls);
}
// Message
if ($contactMessage.val() == "") {
_showErrorMessage($contactMessage, contactErrorMandatoryCls);
}
// reCaptcha
var reCaptchaResponse = grecaptcha.getResponse();
if (reCaptchaResponse.length == 0) {
isFormValid = false;
$("#contact-recaptcha-mandatory-error").addClass(contactErrorRecaptchaMandatoryCls);
}
};
var _reCaptchaRender = function () {
grecaptcha.render('contact-recaptcha', {
'sitekey': 'XXX'
});
};
var _reCaptchaValid = function () {
$contactRecaptchaMandatoryError.removeClass(contactErrorRecaptchaMandatoryCls);
};
var _showErrorMessage = function (el, msg) {
el.addClass(contactErrorMandatoryCls);
el.parent().find("." + msg).fadeIn();
if (!isFocusOn) {
el.focus();
isFocusOn = true;
}
isFormValid = false;
};
更奇怪的是,他们能够使用 reCaptcha 破解表单,还可以在主题中发送空值。
如果一切正常,我会在 Contact.SubmitOnSuccess 中提交:
var _submitOnSuccess = function (ajaxResult) {
sentResultOk = ajaxResult.Success;
$sentModal.load("/home/contactsent?cta=" + $contactCTA.val(), function () {
if (sentResultOk == true) {
$("#" + sentModalOkId).show();
}
else {
$("#" + sentModalErrorId).show();
}
$sentModal.fadeIn(function () {
$contactForm[0].reset();
grecaptcha.reset();
$submitBtn.removeClass("submitting");
$submitBtn.prop('disabled', false);
$submitBtn.val("Enviar");
});
});
【问题讨论】:
-
在您的服务器端代码中,您在哪里验证 reCaptcha 结果?我在这里只看到客户端代码。
-
如果您依靠客户端来告诉您它是否有效,那么这就解释了它被黑客入侵的原因。黑客只是告诉你它是有效的。你必须verify the user's response with Google 来验证他们确实解决了验证码,而不仅仅是告诉你他们已经解决了。
-
客户端不需要执行 JavaScript,甚至不需要在 Web 浏览器中与之交互。他们可以向您的服务器发送他们喜欢的任何请求。由您的 服务器端 代码来验证该请求。永远不要相信来自客户的任何东西。
-
基本上当用户向服务器提交表单时,该表单应该包含 reCaptcha 响应令牌。在服务器端代码中,您将验证表单(如果无效则返回错误),然后使用 Google 验证令牌(如果无效则返回错误),然后如果一切都有效,则处理表单。
-
也许,也许不是。如何处理任何给定的错误取决于您。也许客户端验证有一个错误,也许 reCaptcha 暂时存在连接问题等。您不需要假设用户正在做一些恶意的事情,只需适当地处理验证即可。因此,如果他们没有做恶意的事情,他们会看到一个有用的错误。如果他们正在做一些恶意的事情,他们看到的所有都是一个有用的错误。
标签: jquery ajax asp.net-mvc forms