Asp.net mvc 在服务器往返和随后重新生成验证码后验证验证码
我正在根据Sanderson的书Pro ASP.NET MVC框架在表单提交中实现CAPTCHA 视图字段由以下内容生成:Asp.net mvc 在服务器往返和随后重新生成验证码后验证验证码,asp.net-mvc,Asp.net Mvc,我正在根据Sanderson的书Pro ASP.NET MVC框架在表单提交中实现CAPTCHA 视图字段由以下内容生成: <%= Html.Captcha("testCaptcha")%> <%= Html.TextBox("attemptCaptcha")%> public static string Captcha(this HtmlHelper html, string name) { // Pick a GUID to represent this c
<%= Html.Captcha("testCaptcha")%>
<%= Html.TextBox("attemptCaptcha")%>
public static string Captcha(this HtmlHelper html, string name)
{
// Pick a GUID to represent this challenge
string challengeGuid = Guid.NewGuid().ToString();
// Generate and store a random solution text
var session = html.ViewContext.HttpContext.Session;
session[SessionKeyPrefix + challengeGuid] = MakeRandomSolution();
// Render an <IMG> tag for the distorted text,
// plus a hidden field to contain the challenge GUID
var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
string url = urlHelper.Action("Render", "CaptchaImage", new{challengeGuid});
return string.Format(ImgFormat, url) + html.Hidden(name, challengeGuid);
}
但是,这样做会生成一个新的GUID,该GUID会生成新的验证码文本
但是,问题是,验证码隐藏字段值和验证码图像url都保留原始GUID。因此,您永远无法输入正确的值。你基本上只有一次机会把它做好
我对所有这些都不熟悉,但这与视图保留第一页加载的值有关
验证码是通过以下方式生成的:
<%= Html.Captcha("testCaptcha")%>
<%= Html.TextBox("attemptCaptcha")%>
public static string Captcha(this HtmlHelper html, string name)
{
// Pick a GUID to represent this challenge
string challengeGuid = Guid.NewGuid().ToString();
// Generate and store a random solution text
var session = html.ViewContext.HttpContext.Session;
session[SessionKeyPrefix + challengeGuid] = MakeRandomSolution();
// Render an <IMG> tag for the distorted text,
// plus a hidden field to contain the challenge GUID
var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
string url = urlHelper.Action("Render", "CaptchaImage", new{challengeGuid});
return string.Format(ImgFormat, url) + html.Hidden(name, challengeGuid);
}
用guid重新构建目标字段名怎么样?那么,每个字段都是唯一的,不会保留前几代表单的值吗
还是我只需要一个不同的验证码实现?因此,我决定实现reCaptcha。我也定制了自己的观点:
<div id="recaptcha_image"></div>
<a href="#" onclick="Recaptcha.reload();">
generate a new image
</a><br />
<input type="text" name="recaptcha_response_field"
id="recaptcha_response_field" />
<%= Html.ValidationMessage("attemptCaptcha")%>
<script type="text/javascript"
src="http://api.recaptcha.net/challenge?k=[my public key]"></script>
所有这些都假设您已经实现了Action Filter属性和view helper,如recaptcha.net所述:
public class CaptchaValidatorAttribute : ActionFilterAttribute
{
private const string CHALLENGE_FIELD_KEY = "recaptcha_challenge_field";
private const string RESPONSE_FIELD_KEY = "recaptcha_response_field";
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var captchaChallengeValue =
filterContext.HttpContext.Request.Form[CHALLENGE_FIELD_KEY];
var captchaResponseValue =
filterContext.HttpContext.Request.Form[RESPONSE_FIELD_KEY];
var captchaValidtor = new Recaptcha.RecaptchaValidator
{
PrivateKey = "[my private key]",
RemoteIP = filterContext.HttpContext.Request.UserHostAddress,
Challenge = captchaChallengeValue,
Response = captchaResponseValue
};
var recaptchaResponse = captchaValidtor.Validate();
// this will push the result value into a parameter in our Action
filterContext.ActionParameters["captchaValid"] = recaptchaResponse.IsValid;
base.OnActionExecuting(filterContext);
}
}
html帮助程序:
public static class Captcha
{
public static string GenerateCaptcha( this HtmlHelper helper )
{
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "clean",
PublicKey = "[my public key]",
PrivateKey = "[ my private key ]"
};
var htmlWriter = new HtmlTextWriter( new StringWriter() );
captchaControl.RenderControl(htmlWriter);
return htmlWriter.InnerWriter.ToString();
}
}
希望这能帮助那些被书中的实现困住的人。我在使用Sanderson书中的captcha示例时也遇到了同样的问题。问题是,页面被浏览器缓存,在验证码测试失败后不会刷新。因此,它总是显示相同的图像,即使生成并存储了新的验证码以供测试 一种解决方案是在尝试失败后重新加载页面时强制浏览器刷新页面;如果只返回View(),则不会发生这种情况。您可以使用RedirectToAction(“SubmiteSay”)执行此操作,它将命中接受HttpVerbs.Get的操作方法 当然,您将无法使用ViewData通知用户错误,但您可以将其包含在查询字符串中,然后只检查查询字符串以显示消息 所以,以这本书为例
if (!CaptchaHelper.VerifyAndExpireSolution(HttpContext, captcha, captchaAttempt)
{
RedirectToAction("SubmitEssay", new { fail = 1 });
}
然后只需检查QueryString集合是否包含传递错误消息的“fail”。唯一字段名不起作用。我也经历了同样的事情。目标字段只在第一次创建之后才被缓存,不再重新生成。这可能就是为什么像reCaptcha这样基于javascript的实现可能更好的原因。
public static class Captcha
{
public static string GenerateCaptcha( this HtmlHelper helper )
{
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "clean",
PublicKey = "[my public key]",
PrivateKey = "[ my private key ]"
};
var htmlWriter = new HtmlTextWriter( new StringWriter() );
captchaControl.RenderControl(htmlWriter);
return htmlWriter.InnerWriter.ToString();
}
}
if (!CaptchaHelper.VerifyAndExpireSolution(HttpContext, captcha, captchaAttempt)
{
RedirectToAction("SubmitEssay", new { fail = 1 });
}