tuupola / slim-jwt-auth
Requires
- php: ^7.4|^8.0
- firebase/php-jwt: ^3.0|^4.0|^5.0
- psr/http-message: ^1.0|^2.0
- psr/http-server-middleware: ^1.0
- psr/log: ^1.0|^2.0|^3.0
- tuupola/callable-handler: ^1.0
- tuupola/http-factory: ^1.3
Requires (Dev)
- equip/dispatch: ^2.0
- laminas/laminas-diactoros: ^2.0|^3.0
- overtrue/phplint: ^1.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^7.0|^8.5.30|^9.0
- squizlabs/php_codesniffer: ^3.7
- 3.x-dev
- 3.8.0
- 3.7.0
- 3.6.0
- 3.5.2
- 3.5.1
- 3.5.0
- 3.4.0
- 3.3.0
- 3.2.0
- 3.1.1
- 3.1.0
- 3.0.0
- 3.0.0-rc.5
- 3.0.0-rc.4
- 3.0.0-rc.3
- 3.0.0-rc.2
- 3.0.0-rc.1
- 2.x-dev
- 2.4.0
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.0
- 2.1.0
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- 1.x-dev
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- 0.4.0
- 0.3.0
- 0.2.1
- 0.2.0
- 0.1.1
- 0.1.0
- dev-abandon-notes
- dev-psr-http-message-20
- dev-php-jwt-6
- dev-wrong-php-version
This package is auto-updated.
Last update: 2024-09-11 18:19:11 UTC
README
重要
此包已被废弃。有关替代方案,请参阅jimtools/jwt-auth。
PSR-7和PSR-15 JWT身份验证中间件
此中间件实现了JSON Web Token身份验证。最初是为Slim框架开发的,但也可以与任何使用PSR-7和PSR-15风格中间件的框架一起使用。它已在Slim框架和Zend Expressive框架上进行了测试。
请注意!您正在阅读3.x分支的文档,该分支仅适用于PHP 7.1及以上版本。如果您使用的是较旧的PHP版本,请参阅2.x分支。这两个分支不兼容,有关升级说明,请参阅UPGRADING。
中间件不实现OAuth 2.0授权服务器,也不提供生成、颁发或存储身份验证令牌的方式。它仅在通过标题或cookie传递时解析和验证令牌。例如,当您想使用JSON Web Tokens作为API密钥时,这很有用。
有关示例实现,请参阅Slim API Skeleton。
安装
使用composer安装最新版本。
$ composer require tuupola/slim-jwt-auth
如果使用Apache,请将以下内容添加到.htaccess
文件中。否则,PHP将无法访问Authorization: Bearer
标题。
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
使用方法
配置选项以数组形式传递。唯一必需的参数是secret
,用于验证令牌签名。请注意,secret
不是令牌。这是您用于签署令牌的秘密。
出于简便起见,以下示例显示了硬编码在代码中的secret
。在现实生活中,您应该将其存储在别处。一个好的选择是环境变量。您可以使用dotenv或类似工具进行开发。以下示例假设您正在使用Slim框架。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
以下是一个示例,其中您的秘密存储为环境变量
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => getenv("JWT_SECRET") ]));
当发出请求时,中间件会尝试验证和解码令牌。如果找不到令牌或验证和解码时发生错误,服务器将以401 Unauthorized
响应。
当令牌被篡改或令牌过期时,会触发验证错误。有关所有可能的验证错误,请参阅JWT库源代码。
可选参数
路径
可选的path
参数允许您指定网站的受保护部分。它可以是字符串或数组。您不需要指定每个URL。相反,将path
设置视为文件夹。在以下示例中,以/api
开头的所有内容都将被认证。如果您不定义path
,则所有路由都将受保护。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "path" => "/api", /* or ["/api", "/admin"] */ "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
忽略
使用可选的ignore
参数,您可以对path
参数进行例外处理。在下面的示例中,所有以/api
和/admin
开头的路径都将进行身份验证,但/api/token
和/admin/ping
将不会进行身份验证。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "path" => ["/api", "/admin"], "ignore" => ["/api/token", "/admin/ping"], "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
头部
默认情况下,中间件会尝试从Authorization
头部中查找令牌。您可以使用header
参数更改头部名称。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "header" => "X-Token", "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
正则表达式
默认情况下,中间件假定头部值的格式为Bearer <token>
。您可以使用regexp
参数更改此行为。例如,如果您有自定义头部,例如X-Token: <token>
,则应传递头部和正则表达式参数。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "header" => "X-Token", "regexp" => "/(.*)/", "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
Cookie
如果既没有从环境变量也没有从头部找到令牌,则中间件会尝试从名为token
的Cookie中找到它。您可以使用cookie
参数更改Cookie名称。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "cookie" => "nekot", "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
算法
您可以通过algorithm
参数设置支持算法。这可以是字符串或字符串数组。默认值为["HS256", "HS512", "HS384"]
。支持的算法有HS256
、HS384
、HS512
和RS256
。请注意,同时启用HS256
和RS256
是一个安全风险。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub", "algorithm" => ["HS256", "HS384"] ]));
属性
当令牌成功解码且身份验证成功时,解码后的令牌内容将作为token
属性保存到$request
对象中。您可以使用attribute
参数更改此设置。设置为null
或false
以禁用此行为
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "attribute" => "jwt", "secret" => "supersecretkeyyoushouldnotcommittogithub" ])); /* ... */ $decoded = $request->getAttribute("jwt");
记录器
可选的logger
参数允许您传入一个PSR-3兼容的记录器,以帮助调试或其他应用程序记录需求。
use Monolog\Logger; use Monolog\Handler\RotatingFileHandler; $app = new Slim\App; $logger = new Logger("slim"); $rotating = new RotatingFileHandler(__DIR__ . "/logs/slim.log", 0, Logger::DEBUG); $logger->pushHandler($rotating); $app->add(new Tuupola\Middleware\JwtAuthentication([ "path" => "/api", "logger" => $logger, "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
之前
仅在身份验证成功但在调用下一个中间件之前调用之前函数。您可以使用此函数在传递给下一个中间件之前更改请求。如果返回值不是Psr\Http\Message\ServerRequestInterface
,则将忽略返回值。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub", "before" => function ($request, $arguments) { return $request->withAttribute("test", "test"); } ]));
之后
仅在身份验证成功且已调用传入中间件堆栈之后调用之后函数。您可以使用此函数在传递给堆栈中的下一个传出中间件之前更改响应。如果返回值不是Psr\Http\Message\ResponseInterface
,则将忽略返回值。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub", "after" => function ($response, $arguments) { return $response->withHeader("X-Brawndo", "plants crave"); } ]));
请注意,after和before回调函数都通过
$arguments
参数接收原始令牌字符串以及解码后的声明。
错误
当身份验证失败时调用错误。它接收最后的错误信息作为参数。您可以使用此功能,例如返回JSON格式的错误响应。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub", "error" => function ($response, $arguments) { $data["status"] = "error"; $data["message"] = $arguments["message"]; $response->getBody()->write( json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) ); return $response->withHeader("Content-Type", "application/json") } ]));
规则
可选的rules
参数允许您传入定义请求是否应进行身份验证的规则。规则是一个可调用的,接收请求作为参数。如果任何规则返回布尔值false
,则请求将不会被身份验证。
默认情况下,中间件配置如下。所有路径都使用所有请求方法(除了OPTIONS
)进行身份验证。
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "rules" => [ new Tuupola\Middleware\JwtAuthentication\RequestPathRule([ "path" => "/", "ignore" => [] ]), new Tuupola\Middleware\JwtAuthentication\RequestMethodRule([ "ignore" => ["OPTIONS"] ]) ] ]));
RequestPathRule包含一个path
参数和一个ignore
参数。后者包含不应进行身份验证的路径。RequestMethodRule包含不应进行身份验证的请求方法的ignore
参数。将ignore
视为白名单。
在99%的情况下,您不需要使用rules
参数。它仅用于默认值不适用时的特殊情况。
安全
JSON Web Tokens本质上相当于密码。您应该将其视为密码,并且始终使用HTTPS。如果中间件检测到在HTTP上的不安全使用,则将抛出RuntimeException
。默认情况下,对于运行在localhost
上的服务器,此规则较宽松。要允许不安全的使用,您必须手动将其设置为false
。
$app->add(new Tuupola\Middleware\JwtAuthentication([ "secure" => false, "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
另外,您也可以列出多个开发服务器以使用宽松的安全设置。以下设置允许 localhost
和 dev.example.com
接收未加密的请求。
$app->add(new Tuupola\Middleware\JwtAuthentication([ "secure" => true, "relaxed" => ["localhost", "dev.example.com"], "secret" => "supersecretkeyyoushouldnotcommittogithub" ]));
授权
默认情况下,中间件仅进行身份验证,这并不有趣。JWT 的优点在于您可以在令牌中传递额外的数据。这些数据可以包括用于授权的范围等。
如何实现令牌数据的存储或可能的授权实施取决于您。
假设您有一个包含范围数据的令牌。默认情况下,中间件将令牌内容保存到请求的 token
属性。
[ "iat" => "1428819941", "exp" => "1744352741", "scope" => ["read", "write", "delete"] ]
$app = new Slim\App; $app->add(new Tuupola\Middleware\JwtAuthentication([ "secret" => "supersecretkeyyoushouldnotcommittogithub" ])); $app->delete("/item/{id}", function ($request, $response, $arguments) { $token = $request->getAttribute("token"); if (in_array("delete", $token["scope"])) { /* Code for deleting item */ } else { /* No scope so respond with 401 Unauthorized */ return $response->withStatus(401); } });
测试
您可以选择手动或自动在每次代码更改时运行测试。自动测试需要 entr 运行。
$ make test
$ brew install entr $ make watch
贡献
有关详细信息,请参阅 CONTRIBUTING。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 tuupola@appelsiini.net 而不是使用问题跟踪器来报告。
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。