tuupola/slim-basic-auth

PSR-7 和 PSR-15 HTTP 基本认证中间件

3.3.1 2020-10-28 15:22 UTC

README

此中间件实现了 HTTP 基本认证。它最初是为 Slim 开发的,但可以与所有使用 PSR-7 或 PSR-15 风格中间件的框架一起使用。它已在 Slim 框架Zend Expressive 上进行测试。

Latest Version Packagist Software License Build Status Coverage

请注意!您正在阅读 3.x 分支的文档 3.x branch,它仅适用于 PHP 7.1 及以上版本。如果您正在使用较旧版本的 PHP,请参阅 2.x 分支。这两个分支不兼容,有关升级说明,请参阅 UPGRADING

安装

使用 composer 安装最新版本。

$ composer require tuupola/slim-basic-auth

使用方法

配置选项作为数组传递。必需参数是 users。这是一个数组,您可以在其中传递一个或多个 "username" => "password" 组合。用户名是键,密码是值。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

与 Zend Expressive 相同。

$app = Zend\Expressive\AppFactory::create();

$app->pipe(new Tuupola\Middleware\HttpBasicAuthentication([
    "users" => [
        "root" => "t00r",
        "user" => "passw0rd"
    ]
]));

以下示例假设您正在使用 Slim 框架。

明文密码仅适用于快速测试。您可能想使用散列密码。可以使用 htpasswd 命令行工具或 password_hash() PHP 函数生成散列密码。

$ htpasswd -nbBC 10 root t00r
root:$2y$10$1lwCIlqktFZwEBIppL4ak.I1AHxjoKy9stLnbedwVMrt92aGz82.O
$ htpasswd -nbBC 10 somebody passw0rd
somebody:$2y$10$6/vGXuMUoRlJUeDN.bUWduge4GhQbgPkm6pfyGxwgEWT0vEkHKBUW
$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "users" => [
        "root" => '$2y$10$1lwCIlqktFZwEBIppL4ak.I1AHxjoKy9stLnbedwVMrt92aGz82.O',
        "somebody" => '$2y$10$6/vGXuMUoRlJUeDN.bUWduge4GhQbgPkm6pfyGxwgEWT0vEkHKBUW'
    ]
]));

即使您使用散列密码,将凭据存储在代码中也不是一个好主意。相反,您可以将它们存储在环境变量中或外部文件中,这些文件不会提交到 GitHub。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "users" => [
        "admin" => getenv("ADMIN_PASSWORD")
    ]
]));

可选参数

路径

可选的 path 参数允许您指定网站的受保护部分。它可以是字符串或数组。您不需要指定每个 URL。相反,将 path 设置视为文件夹。在下面的示例中,所有以 /api 开头的 URL 都将进行认证。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/api", /* or ["/admin", "/api"] */
    "realm" => "Protected",
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

忽略

使用可选的 ignore 参数,您可以针对 path 参数进行例外处理。在下面的示例中,所有以 /api/admin 开头的 URL 都将进行认证,但 /api/token/admin/ping 除外,它们将不进行认证。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => ["/api", "/admin"],
    "ignore" => ["/api/token", "/admin/ping"],
    "realm" => "Protected",
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

之前

只有当认证成功时才会调用 before 函数,但在调用下一个传入的中间件之前。您可以使用此功能在将请求传递给堆栈中的下一个传入中间件之前更改请求。如果返回值不是 \Psr\Http\Message\RequestInterface,则返回值将被忽略。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ],
    "before" => function ($request, $arguments) {
        return $request->withAttribute("user", $arguments["user"]);
    }
]));

之后

只有当认证成功并且已经调用传入的中间件堆栈之后,才会调用 after 函数。您可以使用此功能在将响应传递给堆栈中的下一个传出中间件之前更改响应。如果返回值不是 \Psr\Http\Message\ResponseInterface,则返回值将被忽略。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ],
    "after" => function ($response, $arguments) {
        return $response->withHeader("X-Brawndo", "plants crave");
    }
]));

安全

基本认证以明文形式传输凭据。因此,始终应与基本认证一起使用 HTTPS。如果中间件检测到通过 HTTP 的不安全使用,它将抛出带有以下消息的 RuntimeExceptionInsecure use of middleware over HTTP denied by configuration

默认情况下,localhost 可以使用 HTTP。也可以配置 HttpBasicAuthentication 的安全行为,允许

如何配置白名单

您可以列出允许不安全访问的主机。例如,要允许开发主机 dev.example.com 的 HTTP 流量,请将主机名添加到 relaxed 配置密钥。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "secure" => true,
    "relaxed" => ["localhost", "dev.example.com"],
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

允许 HTTPS 终止和转发

如果公共流量在负载均衡器或代理上终止 SSL 并不安全地转发到应用程序主机,HttpBasicAuthentication 可以检查请求头以确保原始客户端请求是安全发起的。要启用,请将字符串 headers 添加到 relaxed 配置密钥。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "secure" => true,
    "relaxed" => ["localhost", "headers"],
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

允许所有未加密流量

要允许任何主机不安全使用,您必须手动将其设置为 false。这通常不是一个好主意。只有在您知道自己在做什么的情况下才使用。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "secure" => false,
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

自定义认证方法

有时仅通过数组传递用户还不够。要针对自定义数据源进行认证,您可以将可调用的对象作为 authenticator 参数传递。这可以是实现 AuthenticatorInterface 的类或匿名函数。可调用的对象接收一个包含 userpassword 的数组作为参数。在两种情况下,认证器都必须返回 truefalse

如果您正在创建一个随机允许人们登录的企业™ 软件,您可以使用以下方法。

use Tuupola\Middleware\HttpBasicAuthentication\AuthenticatorInterface;
use Tuupola\Middleware\HttpBasicAuthentication;

class RandomAuthenticator implements AuthenticatorInterface {
    public function __invoke(array $arguments): bool {
        return (bool)rand(0,1);
    }
}

$app = new Slim\App;

$app->add(new HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "authenticator" => new RandomAuthenticator
]));

同样,匿名函数也可以实现相同的功能。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "authenticator" => function ($arguments) {
        return (bool)rand(0,1);
    }
]));

设置认证失败时的响应体

默认情况下,插件返回一个空的响应体和 401 响应。您可以通过提供错误处理器来返回自定义体。例如,当您需要附加信息来解释为什么认证失败时,这很有用。

$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/api",
    "realm" => "Protected",
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ],
    "error" => function ($response, $arguments) {
        $data = [];
        $data["status"] = "error";
        $data["message"] = $arguments["message"];

        $body = $response->getBody();
        $body->write(json_encode($data, JSON_UNESCAPED_SLASHES));

        return $response->withBody($body);
    }
]));

与 PDO 的使用

对于那些急于求成的人来说,有一个现成的 PDO 认证器。它涵盖了大多数用例。您可能最终还是要自己实现。

use Tuupola\Middleware\HttpBasicAuthentication\PdoAuthenticator;

$pdo = new PDO("sqlite:/tmp/users.sqlite");
$app = new Slim\App;

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "authenticator" => new PdoAuthenticator([
        "pdo" => $pdo
    ])
]));

为了更好的解释,请参阅 Basic Authentication from Database 博客文章。

与 FastCGI 的使用

默认情况下,Apache 不将凭据传递给 FastCGI 进程。如果您使用 mod_fcgi,您可以使用以下方式配置授权头:

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization

测试

您可以通过手动或自动在每次代码更改时运行测试来运行测试。自动测试需要 entr 运行。

$ make test
$ brew install entr
$ make watch

贡献

有关详细信息,请参阅 CONTRIBUTING

安全

如果您发现任何与安全相关的问题,请通过电子邮件 [email protected] 联系,而不是使用问题跟踪器。

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 LICENSE