1

新しいプロジェクトの Web API を構築するために Restler を試しています。
要件の 1 つは簡易認証です。
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();
?>

Web ページに移動すると、標準のログインとパスワードのフォームが表示されますが、正しいユーザー名とパスワードを入力しても何も起こりません - ログイン ウィンドウが再度開きます。

私はおそらくばかげた間違いを犯していますが、それを見つけることができません。初めてのベーシック認証なのでよろしくお願いします。

サーバーで特別な設定が必要ですか?

編集:
サーバーが 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]

両方を組み合わせる方法は?

4

1 に答える 1

2

理由はわかりませんがiUseAuthenticationBasicAuthenticationクラスに実装する必要がありました。(おそらくこれは 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";
    }
}
?>
于 2013-09-27T06:06:30.403 に答える