Introduction
ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enable a clean separation of concerns and that gives you full control over markup for enjoyable, agile development.
ASP.NET MVC includes many features that enable fast, TDD-friendly development for creating sophisticated applications that use the latest web standards.
You can also choose an existing platform based on ASP.NET MVC from Microsoft Gallery, from:
- Blogs
- CMS
- eCommerce
- Forums
- Galleries
- Wiki
- And more
But one thing that you probably need to add to any Web Application is BOTS Protection and Email Integrity.
So how can
you prevent abuse from "bots", automated programs usually written to generate spam, and how to make sure the user has given you his real email address when registering
on your Web Application?
The answer is: reCAPTCHA and Email Confirmation
reCAPTCHA
A CAPTCHA is a program that can tell whether its user is a human or a computer. You've probably seen them — colorful images with distorted text at the bottom of Web registration forms. CAPTCHAs are used by many websites to prevent abuse from "bots," or automated programs usually written to generate spam. No computer program can read distorted text as well as humans can, so bots cannot navigate sites protected by CAPTCHAs.
Step 1: Download and Get reCAPTCHA Keys
First go to the reCAPTCHA site and register for a unique key, then
Download reCAPTCHA .NET Library.
Save your Public and Private keys safely.
Step 2: Create ASP.NET MVC 3 Web Application
Now, let’s start a new ASP.NET MVC 3 Web Application Project in Visual Studio 2010.
Choose to create from “Internet Application” template
Step 3: Recaptcha
Add the Recaptcha DLL as a reference to your project.
Modify site Web.config with new keys under the appSettings
section and add the keys we received before.
ReCaptchaPrivateKey
ReCaptchaPublicKey
Step 4: Change Registration
Open the Controllers folder, open the AccountController file, and locate the
Register
method, add the new attribute:
[RecaptchaControlMvc.CaptchaValidatorAttribute]
And add the reCAPTCHA logic to your registration code:
[HttpPost]
[RecaptchaControlMvc.CaptchaValidatorAttribute]
public ActionResult Register(RegisterModel model, bool captchaValid)
{
if (!captchaValid)
{
ModelState.AddModelError("", "You did not type the verification
word correctly. Please try again.");
}
else
{
if (ModelState.IsValid)
{
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password,
model.Email, null, null, true, null,
out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("",
ErrorCodeToString(createStatus));
}
}
}
return View(model);
}
Now place the following command in the Register.cshtml file:
@Html.Raw(Html.GenerateCaptcha())
Run your web site and enter the registration page, now you have to enter captcha before compiling the registration.
Email Confirmation
In order to make sure the user has gave you his real email you need to use Email Confirmation mechanism to your site.
ASP MVC is doing some of the work for us, when a user is register to your site is assign with a unique ID (GUID) property called - ProviderUserKey
I’ll use this value to verify the account.
Step 1: Modify Web.Config with SMTP Settings
Before we get started with the Email Confirmation implementation we need to define our email settings, to do so I’ve used my Gmail account (just for this test) and add those values in the
web.config just below the configuration tag.
<configuration>
<system.net>
<mailSettings>
<smtp deliveryMethod="Network">
<network host="smtp.gmail.com" port="587"
userName="[YourName@Gmail.com]"
password="[Your Password]" />
</smtp>
</mailSettings>
</system.net>
Step 2: Add Confirmation View
After the user has register we want to redirect him to a confirmation page and tell him to check his email for the confirmation link, so:
Add a new View called – Confirmation
@{
ViewBag.Title = "Email Confirmation";
}
<h2>
Confirmation</h2>
<p>
Thank you for registering. Please check your email for a confirmation
request with a link that will confirm your account. Once you click the
link, your registration will be complete.</p>
In the AccountController
add
the result for confirmation.
public ActionResult Confirmation()
{
return View();
}
Step 3: Send Mail
Before changing the registration we need to create the email functionality, this confirmation email will contain the
ProviderUserKey
and a direct link to our site.
The SendConfirmationEmail
method will receive the UserName,
and using Membership.GetUser
we’ll be able to get all the information on that user and of course the
ProviderUserKey
.
I’ve built the confirmation URL using HttpContext
and combined the User Guid ID and the site.
var verifyUrl = HttpContext.Current.Request.Url.GetLeftPart
(UriPartial.Authority) + "/Account/Verify/" + confirmationGuid;
public class EmailManager
{
private const string EmailFrom = "noreplay@gmail.com";
public static void SendConfirmationEmail(string userName)
{
var user = Membership.GetUser(userName.ToString());
var confirmationGuid = user.ProviderUserKey.ToString();
var verifyUrl = HttpContext.Current.Request.Url.GetLeftPart
(UriPartial.Authority) + "/Account/Verify/" + confirmationGuid;
using (var client = new SmtpClient())
{
using (var message = new MailMessage(EmailFrom, user.Email))
{
message.Subject = "Please Verify your Account";
message.Body = "<html><head><meta content=\"text/html;
charset=utf-8\" /></head><body><p>Dear " + user.UserName +
", </p><p>To verify your account, please click the following link:</p>"
+ "<p><a href=\"" + verifyUrl + "\" target=\"_blank\">" + verifyUrl + "
+"</a></p><div>Best regards,</div><div>Someone</div><p>Do not forward "
+"this email. The verify link is private.</p></body></html>";
message.IsBodyHtml = true;
client.EnableSsl = true;
client.Send(message);
};
};
}
}
Step 4: Change Registration
Now we need to change the Registration functionality.
The main thing is when creating a new user we need to change the user state
to Not Approve and instead of performing login, we need to send him an email using our
EmailManager
and show him the confirmation page.
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email,
null, null, false, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
EmailManager.SendConfirmationEmail(model.UserName);
return RedirectToAction("Confirmation", "Account");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
return View(model);
}
Step 5: Add Verify
In AccountController
I’ve added a
Verify
ActionResult. Verify
will receive the User ID, then we’ll check for some bad IDs, if the user is already approved SignOut the user and redirect to the LogOn page, if the user is not approved,
we need to change IsApprove
to true
and call UpdateUser
to update the database with the new changes, also we will do the login for the user and redirect him to the home page.
public ActionResult Verify(string id)
{
if (string.IsNullOrEmpty(id) || (!Regex.IsMatch(id, @"[0-9a-f]{8}\-
([0-9a-f]{4}\-){3}[0-9a-f]{12}")))
{
ViewBag.Msg = "Not Good!!!";
return View();
}
else
{
var user = Membership.GetUser(new Guid(id));
if (!user.IsApproved)
{
user.IsApproved = true;
Membership.UpdateUser(user);
FormsAuthentication.SetAuthCookie(user.UserName, false);
return RedirectToAction("Index", "Home");
}
else
{
FormsAuthentication.SignOut();
ViewBag.Msg = "Account Already Approved";
return RedirectToAction("LogOn");
}
}
}
Links
Enjoy!