Stop Automated Comment Spam on WordPress with Nginx (Updated)

Nginx and WordPress - comment spam After you read this article, please read the update at the end for what may be a easier and better way to stop comment spam on your WordPress website.

I have a simple method of stopping automated comment spam and as far as I can tell, it’s nearly foolproof. It won’t stop human-generated comment spam, but that isn’t an issue. Human-generated comments should be moderated anyway.

There are some complicated WordPress plugins that do the same thing, but my method is ridiculously simple. It requires a single WordPress function and a short web server routine.

Stop Automated Comment Spam with a Single JavaScript Cookie

I got into a mild argument with one plugin author a while back. His complaint about my method is that it won’t work with the comment form if there’s an issue with JavaScript. I’ve used this method for a few months and real commenters, not the spamming kind, don’t seem to have a problem with it.

Setting the cookie is easy. Add a function to WordPress, either through the theme’s function.php file or by using a plugin that adds function snippets. I use the Code Snippets plugin. Here’s the function to insert the JavaScript code to set the cookie in JavaScript:

For HTTP:

function set_post_cookie() {
    echo '<script>document.cookie = "cookie_name=value; path=/;";</script>' . "n"; 
}
add_action( 'comment_form', 'set_post_cookie', 100 );

For HTTPS:

function set_post_cookie() {
    echo '<script>document.cookie = "cookie_name=value; path=/; secure";</script>' . "n"; 
}
add_action( 'comment_form', 'set_post_cookie', 100 );

The only difference in the two is the secure flag. In either case, the “cookie_name” and the “value” of the cookie can be set to almost anything. Use lowercase letters and underscores for simplicity. The add_action priority can be anything above 10 and I use 100 because I want it to run after everything else.

Check and Reject with Nginx

I don’t know how to do it with Apache or any other web server. I haven’t used Apache in years. Here’s how to check to see if the cookie exists at the server context level (replace “cookie_name”) and reject the PHP comment script if it doesn’t:

if ($request_uri ~* /wp.comments.post.php) { set $comment_spam_flag 1; }
if ($http_cookie ~* cookie_name) { set $comment_spam_flag 0; }
if ($comment_spam_flag) { return 403; }


I’m well aware that this can be done with PHP from within WordPress, but why would you do it that way? Setting a cookie with JavaScript and checking it with the web server means PHP and MySQL (or MariaDB) won’t be touched. It may not work at all with PHP if the page is cached.

JavaScript Issues

Most people use [relatively] modern web browsers with JavaScript turned on when attempting to post comments. Anyone using a web browser with JavaScript turned off isn’t likely to post a comment anywhere. It’s a safe bet 99.99 percent of the “real” people commenting won’t have a problem doing so.

In the past six months, I’ve only received two comments that looked like they were posted by bots. Two! Most bots can’t accept or process cookies regardless of how you set the cookies.

I was inspired by a very old WordPress plugin called “Cookies for Comments” but my method is much simpler and works whether a page is cached or not.

If you know how to do this in Apache or any other web server, please let me know.

Update

A post at WP Tavern explains the new invisible reCAPTCHA from Google. There’s already a WordPress plugin available.

Share this: