diff --git a/PoliteCaptcha/Const.cs b/PoliteCaptcha/Const.cs
index a412e22..6d8a319 100644
--- a/PoliteCaptcha/Const.cs
+++ b/PoliteCaptcha/Const.cs
@@ -11,6 +11,8 @@ public static class Const
public const string ReCaptchControlId = "RudeCaptcha";
public const string ReCaptchaLocalhostPrivateKey = "6LehOM0SAAAAAC5LsEpHoyyMqJcz7f_zEfqm66um";
public const string ReCaptchaLocalhostPublicKey = "6LehOM0SAAAAAPgsjOy-6_grqy1JiB_W_jJa_aCw";
+ public const string ReCaptchaPrivateKeyAppSettingKey = "reCAPTCHA::PrivateKey";
+ public const string ReCaptchaPublicKeyAppSettingKey = "reCAPTCHA::PublicKey";
public const string ReCaptchaResponseField = "recaptcha_response_field";
}
}
diff --git a/PoliteCaptcha/ErrorMessage.Designer.cs b/PoliteCaptcha/ErrorMessage.Designer.cs
index c574ff6..530aad4 100644
--- a/PoliteCaptcha/ErrorMessage.Designer.cs
+++ b/PoliteCaptcha/ErrorMessage.Designer.cs
@@ -60,6 +60,15 @@ public class ErrorMessage {
}
}
+ ///
+ /// Looks up a localized string similar to The default reCAPTCHA API keys may only be used for local requests. Configure your app's own API keys in app settings..
+ ///
+ public static string DefaultReCaptchApiKeysOnlyAllowedForLocalRequest {
+ get {
+ return ResourceManager.GetString("DefaultReCaptchApiKeysOnlyAllowedForLocalRequest", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The HTTP context must not be null..
///
diff --git a/PoliteCaptcha/ErrorMessage.resx b/PoliteCaptcha/ErrorMessage.resx
index beb17d9..8e77047 100644
--- a/PoliteCaptcha/ErrorMessage.resx
+++ b/PoliteCaptcha/ErrorMessage.resx
@@ -117,6 +117,9 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ The default reCAPTCHA API keys may only be used for local requests. Configure your app's own API keys in app settings.
+
The HTTP context must not be null.
diff --git a/PoliteCaptcha/PoliteCaptcha.csproj b/PoliteCaptcha/PoliteCaptcha.csproj
index 21d63da..de66b84 100644
--- a/PoliteCaptcha/PoliteCaptcha.csproj
+++ b/PoliteCaptcha/PoliteCaptcha.csproj
@@ -37,6 +37,7 @@
..\packages\recaptcha.1.0.5.0\lib\.NetFramework 4.0\Recaptcha.dll
+
diff --git a/PoliteCaptcha/ReCaptchaGenerator.cs b/PoliteCaptcha/ReCaptchaGenerator.cs
index a04fdc6..5cae18d 100644
--- a/PoliteCaptcha/ReCaptchaGenerator.cs
+++ b/PoliteCaptcha/ReCaptchaGenerator.cs
@@ -1,4 +1,5 @@
using System;
+using System.Configuration;
using System.IO;
using System.Web;
using System.Web.Mvc;
@@ -11,11 +12,32 @@ public class ReCaptchaGenerator : ICaptchaGenerator
{
public IHtmlString Generate(HtmlHelper htmlHelper)
{
+ if (htmlHelper == null)
+ throw new ArgumentNullException("htmlHelper");
+
+ var publicApiKey = ConfigurationManager.AppSettings[Const.ReCaptchaPublicKeyAppSettingKey];
+ if (publicApiKey == null)
+ {
+ if (!htmlHelper.ViewContext.HttpContext.Request.IsLocal)
+ throw new InvalidOperationException(ErrorMessage.DefaultReCaptchApiKeysOnlyAllowedForLocalRequest);
+
+ publicApiKey = Const.ReCaptchaLocalhostPublicKey;
+ }
+
+ var privateApiKey = ConfigurationManager.AppSettings[Const.ReCaptchaPrivateKeyAppSettingKey];
+ if (privateApiKey == null)
+ {
+ if (!htmlHelper.ViewContext.HttpContext.Request.IsLocal)
+ throw new InvalidOperationException(ErrorMessage.DefaultReCaptchApiKeysOnlyAllowedForLocalRequest);
+
+ privateApiKey = Const.ReCaptchaLocalhostPrivateKey;
+ }
+
var recaptchaControl = new RecaptchaControl
{
ID = Const.ReCaptchControlId,
- PublicKey = Const.ReCaptchaLocalhostPublicKey,
- PrivateKey = Const.ReCaptchaLocalhostPrivateKey,
+ PublicKey = publicApiKey,
+ PrivateKey = privateApiKey,
};
var htmlWriter = new HtmlTextWriter(new StringWriter());
diff --git a/PoliteCaptcha/ReCaptchaValidator.cs b/PoliteCaptcha/ReCaptchaValidator.cs
index 3644db9..dffd0a5 100644
--- a/PoliteCaptcha/ReCaptchaValidator.cs
+++ b/PoliteCaptcha/ReCaptchaValidator.cs
@@ -1,4 +1,5 @@
using System;
+using System.Configuration;
using System.Web;
using Recaptcha;
@@ -10,10 +11,7 @@ public class ReCaptchaValidator : ICaptchaValidator
public ReCaptchaValidator()
{
- recaptchaValidator = new RecaptchaValidator
- {
- PrivateKey = Const.ReCaptchaLocalhostPrivateKey,
- };
+ recaptchaValidator = new RecaptchaValidator();
}
public bool Validate(HttpContextBase httpContext)
@@ -21,6 +19,15 @@ public bool Validate(HttpContextBase httpContext)
if (httpContext == null)
throw new ArgumentNullException("httpContext");
+ var privateApiKey = ConfigurationManager.AppSettings[Const.ReCaptchaPrivateKeyAppSettingKey];
+ if (privateApiKey == null)
+ {
+ if (!httpContext.Request.IsLocal)
+ throw new InvalidOperationException(ErrorMessage.DefaultReCaptchApiKeysOnlyAllowedForLocalRequest);
+
+ privateApiKey = Const.ReCaptchaLocalhostPrivateKey;
+ }
+
var challenge = httpContext.Request.Form[Const.ReCaptchaChallengeField];
if (string.IsNullOrWhiteSpace(challenge))
return false;
@@ -29,9 +36,10 @@ public bool Validate(HttpContextBase httpContext)
if (string.IsNullOrWhiteSpace(response))
return false;
+ recaptchaValidator.PrivateKey = privateApiKey;
+ recaptchaValidator.RemoteIP = httpContext.Request.UserHostAddress;
recaptchaValidator.Challenge = challenge;
recaptchaValidator.Response = response;
- recaptchaValidator.RemoteIP = httpContext.Request.UserHostAddress;
return recaptchaValidator.Validate().IsValid;
}
diff --git a/Sample/RequestModels/SendFeedbackRequest.cs b/Sample/RequestModels/SendFeedbackRequest.cs
index 7652faf..32fb838 100644
--- a/Sample/RequestModels/SendFeedbackRequest.cs
+++ b/Sample/RequestModels/SendFeedbackRequest.cs
@@ -8,7 +8,7 @@ public class SendFeedbackRequest
[Required, DataType(DataType.EmailAddress)]
public string EmailAddress { get; set; }
- [Required]
+ [Required, DataType(DataType.MultilineText)]
public string Feedback { get; set; }
}
}
\ No newline at end of file