【问题标题】:Using Basic Authorization as Middleware PSR-7 PSR-15使用基本授权作为中间件 PSR-7 PSR-15
【发布时间】:2019-03-27 16:19:13
【问题描述】:

TD;LR:我试图掌握中间件实现背后的想法。它似乎正在工作,但我该如何正确处理响应,以便它向浏览器显示基本授权登录提示?

--

我正在使用:

运行以下代码:

$middleware = [
    new \Middlewares\ResponseTime(),
    (new \Middlewares\BasicAuthentication([
        'username1' => 'password1',
        'username2' => 'password2'
    ]))->attribute('username')
];

// Default handler for end of collection
$default = function (\GuzzleHttp\Psr7\ServerRequest $request) {
    // Any implementation of PSR-7 ResponseInterface
    return new \GuzzleHttp\Psr7\Response();
};

$collection = new \Equip\Dispatch\MiddlewareCollection($middleware);

// Any implementation of PSR-7 ServerRequestInterface
$request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals();
$response = $collection->dispatch($request, $default);

print_r($response);

返回以下内容:

GuzzleHttp\Psr7\Response Object
(
    [reasonPhrase:GuzzleHttp\Psr7\Response:private] => Unauthorized
    [statusCode:GuzzleHttp\Psr7\Response:private] => 401
    [headers:GuzzleHttp\Psr7\Response:private] => Array
        (
            [WWW-Authenticate] => Array
                (
                    [0] => Basic realm="Login"
                )

            [X-Response-Time] => Array
                (
                    [0] => 16.176ms
                )

        )

    [headerNames:GuzzleHttp\Psr7\Response:private] => Array
        (
            [www-authenticate] => WWW-Authenticate
            [x-response-time] => X-Response-Time
        )

    [protocol:GuzzleHttp\Psr7\Response:private] => 1.1
    [stream:GuzzleHttp\Psr7\Response:private] => 
)

看来middlewares/response-timemiddlewares/http-authentication 执行得很好。但是,我的印象是middlewares/http-authentication 会显示如下的实际登录提示:

但它没有。我想自己实现吗?如果是,我该如何正确地做到这一点?

【问题讨论】:

    标签: php architecture middleware


    【解决方案1】:

    请将领域更改为“我的领域”。

    $middleware = [
        new \Middlewares\ResponseTime(),
        (new \Middlewares\BasicAuthentication([
            'username1' => 'password1',
            'username2' => 'password2'
        ]))->attribute('username')->realm('My realm')
    ];
    

    GuzzleHttp 请求发生在后端,因此它不会像通常在浏览器中那样工作,例如提示输入用户名和密码。当你在不使用任何浏览器的情况下使用 Guzzle 时,你基本上是在模仿一个请求。因此,如果您想要提示,则必须在不使用 GuzzleHttp 的情况下实现此逻辑。

    您仍然可以使用 Guzzle 进行测试,如下所示。

    下面的代码将起作用。

    $request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals()->withHeader('Authorization', 'Basic '.base64_encode('username1:password1'));
    $response = $collection->dispatch($request, $default);
    echo $response->getStatusCode(); //200
    echo $response->getReasonPhrase(); // OK
    

    下面的代码会失败。

    $request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals()->withHeader('Authorization', 'Basic '.base64_encode(''IncorrectUser:IncorrectPassword''));
    $response = $collection->dispatch($request, $default);
    echo $response->getStatusCode(); //401
    echo $response->getReasonPhrase(); // Unauthorized
    

    实现BasicAuthentication 的最佳方式是在中间件框架内。

    Zend 富有表现力

       //Example using your library
       $app->pipe((new \Middlewares\BasicAuthentication([
                        'username1' => 'password1',
                        'username2' => 'password2'
                        ])
                )->attribute('username')->realm('My realm'));
    
        //Example using other library
        $app->pipe(new Tuupola\Middleware\HttpBasicAuthentication([
            "users" => [
                "root" => "t00r",
                "user" => "passw0rd"
            ]
        ]));
    

    上述两个代码都按预期工作。例如在浏览器中提示输入用户名和密码,并允许用户在发送正确的凭据时查看内容。 Guzzle 给您带来了麻烦。

    我希望这会有所帮助。

    【讨论】:

    • 一样,什么也没发生,没有登录提示。
    • 好吧,我通过在顶部添加我自己的header('WWW-Authenticate: Basic realm="My realm"'); 然后使用$_SERVER['PHP_AUTH_*']vars 来传递请求,让它工作了。但这真的是它应该做的方式吗?在此处查看我的完整示例:pastebin.com/Zr3NC9VC
    • 事实证明,我什至不需要包含 ->withHeader('Authorization', 'Basic '.base64_encode($_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW']))->attribute('username')->realm('My realm')
    • 是的,通过添加 if 语句 if (!isset($_SERVER['PHP_AUTH_USER']))... {..} 您没有使用 guzzle,因此 php 将能够通过浏览器捕获用户名和密码。一旦用户输入用户名和密码,它将跳过if 语句,并将捕获的用户名和密码传递给guzzle,如果通过BasicAuthentication 验证,它应该继续进行。我看不出有什么问题。
    • 我已经使用像 Zend expressive 这样的中间件框架对其进行了测试,像 BasicAuthentication 这样的库是为此编写的,并且它可以按预期工作。例如,它会在浏览器中提示我输入用户名和密码,并在正确提交后让我查看页面,类似于您想要的。我提供了 Zend Expressive 的工作示例。
    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 2015-01-08
    • 2015-09-22
    • 1970-01-01
    • 2017-09-13
    • 2014-09-12
    • 2014-01-10
    相关资源
    最近更新 更多