代码之家  ›  专栏  ›  技术社区  ›  Misiu

Restler 3.0基本身份验证

  •  1
  • Misiu  · 技术社区  · 11 年前

    我正在尝试Restler为我的新项目构建web api。
    其中一个要求是简单的身份验证。
    我在SO上找到了一个很好的例子 https://stackoverflow.com/a/7969250/965722 但这是给Restler 2的。 使用手册,我成功地将该类转换为Restler 3.0

    <?php
    class BasicAuthentication implements iAuthenticate
    {
        const REALM = 'Restricted API';
        public static $currentUser;
        public static $requires = 'user';
        public static $role = 'user';
    
        public function __isAllowed()
        {
            if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
            {
                $user = $_SERVER['PHP_AUTH_USER'];
                $pass = $_SERVER['PHP_AUTH_PW'];
                $user = mysql_real_escape_string($user);
                $pass = mysql_real_escape_string($pass);
    
                $roles = array('12345' => 'user', '67890' => 'admin');
    
                if (!isset($pass) || !array_key_exists($pass, $roles))
                {
                    return false;
                }
    
                static ::$role = $roles[$pass];
                Resources::$accessControlFunction = 'AccessControl::verifyAccess';
                return static ::$requires == static ::$role || static ::$role == 'admin';
            }
            header('WWW-Authenticate: Basic realm="' . self::REALM . '"');
            throw new RestException(401, 'Basic Authentication Required');
        }
    
        /**
         * @access private
         */
        public static function verifyAccess(array $m)
        {
            $requires = isset($m['class']['AccessControl']['properties']['requires']) ? $m['class']['AccessControl']['properties']['requires'] : false;
            return $requires ? static ::$role == 'admin' || static ::$role == $requires : true;
        }
    }
    ?>
    

    我的示例api类如下所示:

    <?php
    class Api
    {
        /**
         * @url GET
         * @url GET hello
         * @url GET hello/{to}
         */
        function hello($to = 'world')
        {
            return "Hello $to!";
        }
        /**
         * @access protected
         * @class  AccessControl {@requires user}
         */
        public function user()
        {
            return "protected api, only user and admin can access";
        }
        /**
         * @access protected
         * @class  AccessControl {@requires admin}
         */
        public function admin()
        {
            return "protected api, only admin can access";
        }
    }
    

    任何我的index.php

    <?php
    require_once 'vendor/restler.php';
    use Luracast\Restler\Restler;
    
    $r = new Restler();
    $r->addAPIClass('Api', '');
    $r->addAuthenticationClass('BasicAuthentication');
    $r->handle();
    ?>
    

    当我导航到我的网页时,会显示标准的登录和密码表单,但即使我输入了正确的用户名和密码,也不会发生任何事情——登录窗口会重新打开。

    我可能犯了一些愚蠢的错误,但我找不到。 这是我第一次尝试基本身份验证,所以请耐心等待。

    我需要在服务器上进行一些特殊配置吗?

    编辑:
    看起来我需要一些特殊的配置,因为我的服务器以CGI/FastCGI的方式运行。
    我已尝试从此注释添加代码: http://php.net/manual/en/features.http-auth.php#106285 但我无法正确配置.htaccess。
    这是默认的Restler htaccess文件:

    Options -MultiViews
    DirectoryIndex index.php
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^$ index.php [QSA,L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php [QSA,L]
    </IfModule>
    <IfModule mod_php5.c>
        php_flag display_errors Off
    </IfModule>
    

    并且这些行是从上一个链接到工作的变通方法所需要的:

    RewriteEngine on
    RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
    

    如何将两者结合起来?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Misiu    8 年前

    我不知道为什么,但我必须执行 iUseAuthentication 在我的 BasicAuthentication 班(文档中没有任何关于它的内容,可能是因为这是RC版本,文档和示例都被修改了)。
    就这样,一切都开始运转了。
    我也这样修改了htaccess:

    Options -MultiViews
    DirectoryIndex index.php
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^$ index.php [QSA,L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.php [QSA,L]
        RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
    </IfModule>
    <IfModule mod_php5.c>
        php_flag display_errors Off
    </IfModule>
    

    希望这能帮助到某人:)

    编辑:
    我已经找到了我的代码,并将其发布在这里,也许有人会觉得它很有用。

    <?php
    use \Luracast\Restler\iAuthenticate;
    use \Luracast\Restler\Resources;
    class BasicAuthentication implements iAuthenticate
    {
        const REALM = 'Restricted API';
        public static $requires = 'user';
        public static $role = 'user';
    
        public function __isAllowed()
        {
            //set http auth headers for apache+php-cgi work around
            if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches))
            {
                list($name, $password) = explode(':', base64_decode($matches[1]));
                $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
                $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
            }
    
            //set http auth headers for apache+php-cgi work around if variable gets renamed by apache
            if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches))
            {
                list($name, $password) = explode(':', base64_decode($matches[1]));
                $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
                $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
            }
            if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
            {
                $user = $_SERVER['PHP_AUTH_USER'];
                $pass = $_SERVER['PHP_AUTH_PW'];
    
                $roles = array('12345' => 'user', '67890' => 'admin');
    
                if (!isset($pass) || !array_key_exists($pass, $roles))
                {
                    return false;
                }
    
                static ::$role = $roles[$pass];
                Resources::$accessControlFunction = 'BasicAuthentication::verifyAccess';
                $x = static ::$requires == static ::$role || static ::$role == 'admin';
    
                            $file = 'a.txt';
                $current = file_get_contents($file);
                $current .= static ::$requires." ".static::$role . "\n";
                file_put_contents($file, $current);
    
                return $x;
            }
            header('WWW-Authenticate: Basic realm="' . self::REALM . '"');
            throw new RestException(401, 'Basic Authentication Required');
        }
    
        /**
         * @access private
         */
        public static function verifyAccess(array $m)
        {
            $requires = isset($m['class']['BasicAuthentication']['properties']['requires']) ? $m['class']['BasicAuthentication']['properties']['requires'] : false;
    
                                    $file = 'a.txt';
                $current = file_get_contents($file);
                $current .= $requires." - ".static::$role . "\n";
                file_put_contents($file, $current);
            return $requires ? static ::$role == 'admin' || static ::$role == $requires : true;
        }
    }
    ?>
    

    以及我的示例API类:

    <?php
    class Api implements iUseAuthentication
    {
        private $_authenticated = false;
        /**
         * This method will be called first for filter classes and api classes so
         * that they can respond accordingly for filer method call and api method
         * calls
         *
         *
         * @param bool $isAuthenticated passes true when the authentication is
         *                              done, false otherwise
         *
         * @return mixed
         */
        public function __setAuthenticationStatus($isAuthenticated = false)
        {
            $this->_authenticated = $isAuthenticated;
        }
    
        /**
         * @access protected
         * @class  BasicAuthentication {@requires user}
         */
        public function user()
        {
            return "protected api, only user and admin can access";
        }
        /**
         * @access protected
         * @class  BasicAuthentication {@requires admin}
         */
        public function admin()
        {
            return "protected api, only admin can access";
        }
    }
    ?>