The problem of comment spam
I had a few instances of comment spam in an ASP.NET MVC application that were mildly annoying. Nothing serious, basically the usual kind of link posting rubbish. At first I just deleted them, but had in mind to put in something a bit better.
I had in mind a couple of ideas - the obvious being a captcha, and the second, some way to first identify spam. I am, however, looking for a "nice" way to handle this: the main issue is the site in question should be as low-friction as possible. Right now, all you need to enter is a comment and, if it is the first comment, your name.
Layered Approach
I've initially gone with a layered approach. The initial comment entry appears as is - just a comment textarea and name text box (if the first comment by the user). On submission, if it looks like spam, I'll return with a captcha to complete. On successful completion of the captcha, the comment is allowed. Depending on the success of this approach, I may refine the spam detector to disallow the comment outright rather than simply inserting a captcha if the spam score is above some threshold.
Akismet
I'll first describe the spam detection technique. After a little research, Akismet seems to be popular. This is essentially a web service which you send the comment and a bunch of client information and it replies with a value indicating if it is spam or not.
1) Get a personal Akismet key (assuming you are using it for personal use).
2) Download a .NET client API; I used this one on CodePlex.
3) In your ASP.NET MVC controller action, add something like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Comment([Bind(Prefix = "")] NewCommentModel newComment)
{
if (!AllowPost(newComment.UsersIp, newComment.UserAgent, newComment.CommentText, newComment.Username))
{
newComment.ShowCaptcha = true;
return View(newComment);
}
this.commentService.CreateComment(newComment.Username, newComment.CommentText);
return Redirect(/* view comment url */);
}
private bool AllowPost(string usersIp, string userAgent, string content, string username)
{
var akismet = new Akismet("<your akismet key>", "http://yoursite.com", "UA");
if (!akismet.VerifyKey()) return false;
var comment = new AkismetComment()
{
UserIp = usersIp,
UserAgent = userAgent,
CommentContent = content,
CommentType = "comment",
CommentAuthor = username
};
return !akismet.CommentCheck(comment);
}
Simple as that. Next up, I'll cover the captcha handling.
