diff --git a/security/Security.php b/security/Security.php index 6e960ccbf..c6c6cd402 100644 --- a/security/Security.php +++ b/security/Security.php @@ -146,6 +146,14 @@ class Security extends Controller implements TemplateGlobalProvider { */ private static $frame_options = 'SAMEORIGIN'; + /** + * Value of the X-Robots-Tag header (for the Security section) + * + * @config + * @var string + */ + private static $robots_tag = 'noindex, nofollow'; + /** * Get location of word list file * @@ -326,6 +334,11 @@ class Security extends Controller implements TemplateGlobalProvider { // Prevent clickjacking, see https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options $this->getResponse()->addHeader('X-Frame-Options', $this->config()->frame_options); + + // Prevent search engines from indexing the login page + if ($this->config()->robots_tag) { + $this->getResponse()->addHeader('X-Robots-Tag', $this->config()->robots_tag); + } } public function index() { diff --git a/tests/security/SecurityTest.php b/tests/security/SecurityTest.php index 45463d6fe..a2206e37d 100644 --- a/tests/security/SecurityTest.php +++ b/tests/security/SecurityTest.php @@ -574,6 +574,20 @@ class SecurityTest extends FunctionalTest { Security::$force_database_is_ready = $old; } + public function testSecurityControllerSendsRobotsTagHeader() { + $response = $this->get(Config::inst()->get('Security', 'login_url')); + $robotsHeader = $response->getHeader('X-Robots-Tag'); + $this->assertNotNull($robotsHeader); + $this->assertContains('noindex', $robotsHeader); + } + + public function testDoNotSendEmptyRobotsHeaderIfNotDefined() { + Config::inst()->update('Security', 'robots_tag', null); + $response = $this->get(Config::inst()->get('Security', 'login_url')); + $robotsHeader = $response->getHeader('X-Robots-Tag'); + $this->assertNull($robotsHeader); + } + /** * Execute a log-in form using Director::test(). * Helper method for the tests above