tigerwill90 / xsrf-middleware
基于双重提交模式的 Csrf 保护,cookie - JWT 替代品
Requires
- php: ^7.1
- dflydev/fig-cookies: ^1.0
- psr/http-message: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^1.0
- roave/security-advisories: dev-master
- rybakit/msgpack: ^v0.2
- tuupola/callable-handler: ^0.3
- tuupola/http-factory: ^0.3
Requires (Dev)
- php: ^7.1
- phpstan/phpstan: ^0.9
- phpunit/phpunit: ^7.0
- projek-xyz/slim-monolog: ^0.1
- slim/slim: ^3.9
- squizlabs/php_codesniffer: ^3.0
This package is not auto-updated.
Last update: 2020-08-22 06:50:07 UTC
README
PSR-7 & PSR-15 : CSRF 保护替代 JWT/Branca 认证令牌
基于双重提交模式,cookie - JWT/Branca 替代品进行 Csrf 保护。
它基于 PSR-7 JWT 认证中间件,由 Tuupola 提供。 此中间件旨在与 JWT/Branca 认证方法一起使用,并可用于任何使用 PSR-7 或 PSR-15 风格中间件的框架(自 v1.1.0 版起)。它已在 Slim 框架 上进行了测试。
此中间件不提供生成 Branca/JWT 令牌的方法。但是,您可以在下面的链接中找到生成令牌所需的所有内容。
目标是保护 REST API 免受 跨站请求伪造 攻击,使用双重提交模式(无状态)。
它是如何工作的?
有时您想将 Jwt/Branca 令牌保存在一个 http-only cookie 中。由于无法获取它,您的有效负载内容是安全的。这对于 JWT 特别如此,因为它具有未加密的有效负载。但是,这种保护使您的 API 易受 Csrf 攻击。
当用户登录到网站时
- 生成一个具有伪随机值的反 Csrf
令牌 - 生成
JWT或Branca并将之前生成的令牌设置为有效负载属性之一 - 在
http-only、securecookie 中将JWT或Branca发送到前端 - 在响应体中发送之前生成的
令牌
当认证的 API 消费者想要访问您的 API 时,您需要将反 Csrf 令牌附加为
- 最终一个具有唯一名称的 cookie
- 头属性
- 请求体参数
对于所有不安全的操作 [POST | PUT | PATCH | DELETE],中间件将检查 http-only cookie 中的 令牌 和 JWT 或 Branca,以检查它们是否匹配。如果不匹配,则返回 401 状态。
依赖项
安装
composer require tigerwill90/xsrf-middleware
用法
配置选项作为数组传递。没有必填参数。
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([]));
当请求时,中间件将检查令牌和 cookie 以检查值是否匹配。如果找不到 cookie 或令牌,则服务器将响应 401 未授权
可选参数
路径
可选的 path 参数允许您指定哪些 API 资源受到双重提交模式的保护。它可以是一个字符串或一个数组。您不需要指定每个 URL。
默认参数是 /
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => "/api" /* or ["/api", "/admin"]*/ ]));
在这个例子中,所有以 /api 开头的资源都将受到保护。
中继
可选的 passthrough 参数允许您指定对 path 参数的例外。它可以是字符串或数组。
默认参数是 null
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "passthrough" => "/api/orders" ]));
在这个例子中,所有以 /api 和 /admin 开头的资源都将受到保护,除了 /api/orders
防CSRF
可选的 anticsrf 参数允许您指定防CSRF的cookie、header或参数的名称。
默认参数是 xCsrf
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "anticsrf" => "xCsrf" ]));
在这个例子中,如果存在名为"xCsrf"的cookie、header或请求参数,中间件将比较其值与指定的JWT/Branca令牌claim值。
令牌
根据 PSR-7 JWT身份验证中间件 文档,当令牌成功解码并认证成功时,解码令牌的内容将被保存为$request的属性。可选的 token 参数允许您指定中间件需要在$request中查找的JWT/Branca令牌属性名称。
默认参数是 token
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "token" => "jwt" ]));
有效载荷
或者 您也可以在可选的 payload 参数中传递解码令牌的内容。
默认值是 null
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "payload" => $container["decoded"] ]));
声明
JWT/Branca的美丽之处在于您可以在令牌中传递额外的数据,如角色、权限等。因此,我们可以比较指定的声明与httponly cookie。
[ "uid" => 1, "iat" => "1428819941", "exp" => "1744352741", "aud" => "www.example.com", "roles" => [1,0,1,1,1], "xsrf" => "thepseudorandomvaluegeneratedforbothcookieandtoken" ]
可选的 claim 参数允许您指定中间件需要在解码的JWT/Branca令牌中查找的claim名称。
默认值是 csrf
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "claim" => "xsrf" ]));
根据这个例子,当发送请求到您的API时,您应该在header中有一个名为httponly的cookie和一个authorization token,这两个都设置了值为thepseudorandomvaluegeneratedforbothcookieandtoken。
记录器
可选的 logger 参数允许您传递一个PSR-3兼容的记录器来处理调试。
use Monolog\Logger; use Monolog\Handler\RotatingFileHandler; use Monolog\Formatter\LineFormatter; $app = new Slim\App $logger = new Logger("slim"); $formatter = new LineFormatter( "[%datetime%] [%level_name%]: %message% %context%\n", null, true, true ); $rotating = new RotatingFileHandler(__DIR__ . "/logs/xsrf.log", 0, Logger::DEBUG); $rotating->setFormatter($formatter); $logger->pushHandler($rotating); $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "claim" => "xsrf", "logger" => $logger ]));
在这个例子中,我们将一个Logger $logger实例传递给中间件。
[2017-12-06 01:14:05] [WARNING]: Payload not found in parameter
[2017-12-06 01:14:05] [DEBUG]: Token and cookie don't match, access denied !
错误
当访问被拒绝时,会调用错误。它接受最后一个错误消息作为参数。
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "claim" => "xsrf", "error" => function ($response, $arguments) { $data["message"] = $arguments["message]; return $response ->withHeader("Content-Type", "application/json") ->write(json_encode($data)); } ]));
MessagePack
可选的 msgpack 参数允许您使用 MessagePack 序列化格式。
默认值是 false
$app = new Slim\App $app->add(new Tigerwill90\Middleware\XsrfProtection([ "path" => ["/api", "/admin"], "payload" => $container["decoded"] "msgpack" => true ]));
使用JWT/Branca身份验证中间件的实现
Branca/JWT身份验证中间件需要在Xsrf中间件保护之前运行。
$container = $app->getContainer(); $container["XsrfProtection"] = function($c) { function new \Tigerwill90\Middleware\XsrfProtection([ "path" => "/api", "passthrough" => ["/api/users/signin", "/api/users/token"], "anticsrf" => "xCsrf", "token" => "jwt", "claim" => "xsrf" ]); }; $container["JwtAuthentication"] = function($c) { return new \Slim\Middleware\JwtAuthentication([ "secure" => true, "path" => "/api", "passthrough" => ["/api/users/signin", "/api/users/token"], "attribute" => "jwt", "secret" => getenv("JWT_SECRET") ]); }; $app->add("XsrfProtection"); $app->add("JwtAuthentication");
测试
phpunit
许可
MIT许可证(MIT)。请参阅许可证文件获取更多信息。