Version: current

      1 <?php
      2 /**
      3  * Provides an interface to HTTP basic authentication.
      4  *
      5  * This utility class can be used to secure any request with basic authentication.  To do so,
      6  * {@link BasicAuth::requireLogin()} from your Controller's init() method or action handler method.
      7  *
      8  * It also has a function to protect your entire site.  See {@link BasicAuth::protect_entire_site()}
      9  * for more information.
     10  *
     11  * @package sapphire
     12  * @subpackage security
     13  */
     14 class BasicAuth {
     15     /**
     16      * Flag set by {@link self::protect_entire_site()}
     17      */
     18     private static $entire_site_protected = false;
     19
     20     /**
     21      * Require basic authentication.  Will request a username and password if none is given.
     22      *
     23      * Used by {@link Controller::init()}.
     24      *
     25      * @param string $realm
     26      * @param string|array $permissionCode
     27      * @return Member $member
     28      */
     29     static function requireLogin($realm, $permissionCode) {
     30         if(!Security::database_is_ready() || Director::is_cli()) return true;
     31         $authenticated = false;
     32
     33         if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
     34             $member = MemberAuthenticator::authenticate(array(
     35                 'Email' => $_SERVER['PHP_AUTH_USER'],
     36                 'Password' => $_SERVER['PHP_AUTH_PW'],
     37             ), null);
     38
     39             if($member || Member::currentUser()) $authenticated = true;
     40         }
     41
     42         // If we've failed the authentication mechanism, then show the login form
     43         if(!$authenticated) {
     44             header("WWW-Authenticate: Basic realm=\"$realm\"");
     45             header($_SERVER['SERVER_PROTOCOL'] . ' 401 Unauthorized');
     46
     47             if(isset($_SERVER['PHP_AUTH_USER'])) {
     48                 echo _t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised");
     49             } else {
     50                 echo _t('BasicAuth.ENTERINFO', "Please enter a username and password.");
     51             }
     52
     53             die();
     54         }
     55
     56         if(!Permission::checkMember($member->ID, $permissionCode)) {
     57             header("WWW-Authenticate: Basic realm=\"$realm\"");
     58             header($_SERVER['SERVER_PROTOCOL'] . ' 401 Unauthorized');
     59
     60             if(isset($_SERVER['PHP_AUTH_USER'])) {
     61                 echo _t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator.");
     62             }
     63
     64             die();
     65         }
     66
     67         return $member;
     68     }
     69
     70     /**
     71      * Enable protection of the entire site with basic authentication.
     72      *
     73      * This log-in uses the Member database for authentication, but doesn't interfere with the
     74      * regular log-in form. This can be useful for test sites, where you want to hide the site
     75      * away from prying eyes, but still be able to test the regular log-in features of the site.
     76      *
     77      * If you are including conf/ConfigureFromEnv.php in your _config.php file, you can also enable
     78      * this feature by adding this line to your _ss_environment.php:
     79      *
     80      * define('SS_USE_BASIC_AUTH', true);
     81      *
     82      * @param $protect Set this to false to disable protection.
     83      */
     84     static function protect_entire_site($protect = true) {
     85         return self::$entire_site_protected = $protect;
     86     }
     87
     88     /**
     89      * @deprecated Use BasicAuth::protect_entire_site() instead.
     90      */
     91     static function enable() {
     92         user_error("BasicAuth::enable() is deprecated.  Use BasicAuth::protect_entire_site() instead.", E_USER_NOTICE);
     93         return self::protect_entire_site();
     94     }
     95
     96     /**
     97      * @deprecated Use BasicAuth::protect_entire_site(false) instead.
     98      */
     99     static function disable() {
    100         user_error("BasicAuth::disable() is deprecated.  Use BasicAuth::protect_entire_site(false) instead.", E_USER_NOTICE);
    101         return self::protect_entire_site(false);
    102     }
    103
    104     /**
    105      * Call {@link BasicAuth::requireLogin()} if {@link BasicAuth::protect_entire_site()} has been called.
    106      * This is a helper function used by Controller.
    107      */
    108     static function protect_site_if_necessary() {
    109         if(self::$entire_site_protected) {
    110             self::requireLogin("SilverStripe test website. Use your CMS login.", "ADMIN");
    111         }
    112     }
    113
    114 }
    115

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -