【问题标题】:How do I implement CSRF protection with Slim 4 and slim/csrf?如何使用 Slim 4 和 slim/csrf 实现 CSRF 保护?
【发布时间】:2019-12-31 23:19:36
【问题描述】:

Slim 4 已经在这里,我正在尝试迁移到 Slim 4。一切都很好,但是当我尝试实现它时 CSRF 返回错误。我尝试了最简单的设置,但出现此错误:

Message:传递给 Slim\Csrf\Guard::__invoke() 的参数 2 必须是 Psr\Http\Message\ResponseInterface 的实例,给定的 Slim\Routing\RouteRunner 的实例,在/Volumes/Web/slim/vendor/slim/slim/Slim/MiddlewareDispatcher.php 在第 180 行

文件:/Volumes/Web/slim/vendor/slim/csrf/src/Guard.php

这是我的代码:

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Csrf\Guard;

require __DIR__ . '/../vendor/autoload.php';

/**
 * Instantiate App
 *
 * In order for the factory to work you need to ensure you have installed
 * a supported PSR-7 implementation of your choice e.g.: Slim PSR-7 and a supported
 * ServerRequest creator (included with Slim PSR-7)
 */
$app = AppFactory::create();

$app->add(Guard::class);

// Add Routing Middleware
$app->addRoutingMiddleware();

/*
 * Add Error Handling Middleware
 *
 * @param bool $displayErrorDetails -> Should be set to false in production
 * @param bool $logErrors -> Parameter is passed to the default ErrorHandler
 * @param bool $logErrorDetails -> Display error details in error log
 * which can be replaced by a callable of your choice.

 * Note: This middleware should be added last. It will not handle any exceptions/errors
 * for middleware added after it.
 */
$errorMiddleware = $app->addErrorMiddleware(true, true, true);

// Define app routes
$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write('Hello');
    return $response;
});

// Run app
$app->run();

非常感谢任何帮助!谢谢!

【问题讨论】:

  • 看起来您正在尝试实现 CSRF Token 而不是执行 CSRF attack,但您的问题标题暗示您正在尝试执行 csrf 攻击而不是实现令牌跨度>
  • @hanshenrik,我正在尝试实现一个 CSRF 令牌。

标签: php csrf slim middleware slim-4


【解决方案1】:

该软件包与 Slim4 不兼容。我写了一个包装器,所以你可以使用它。

`

<?php

declare(strict_types=1);

namespace App\Application\Middleware;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Csrf\Guard as Guard;

class CsrfMiddleware extends Guard implements Middleware
{

    /**
     * Process middleware
     *
     * @param  ServerRequestInterface  $request  request object
     * @param  RequestHandlerInterface $handler handler object
     *
     * @return ResponseInterface response object
     */
    public function process(Request $request, RequestHandler $handler): Response
    {
        $this->validateStorage();
        // Validate POST, PUT, DELETE, PATCH requests
        if (in_array($request->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) {
            $body = $request->getParsedBody();
            $body = $body ? (array) $body : [];
            $name = isset($body[$this->prefix . '_name']) ? $body[$this->prefix . '_name'] : false;
            $value = isset($body[$this->prefix . '_value']) ? $body[$this->prefix . '_value'] : false;
            if (!$name || !$value || !$this->validateToken($name, $value)) {
                // Need to regenerate a new token, as the validateToken removed the current one.
                $request = $this->generateNewToken($request);

                $failureCallable = $this->getFailureCallable();
                return $failureCallable($request, $handler);
            }
        }
        // Generate new CSRF token if persistentTokenMode is false, or if a valid keyPair has not yet been stored
        if (!$this->persistentTokenMode || !$this->loadLastKeyPair()) {
            $request = $this->generateNewToken($request);
        } elseif ($this->persistentTokenMode) {
            $pair = $this->loadLastKeyPair() ? $this->keyPair : $this->generateToken();
            $request = $this->attachRequestAttributes($request, $pair);
        }
        // Enforce the storage limit
        $this->enforceStorageLimit();

        return $handler->handle($request);
    }

    /**
     * Getter for failureCallable
     *
     * @return callable|\Closure
     */
    public function getFailureCallable()
    {
        if (is_null($this->failureCallable)) {
            $this->failureCallable = function (Request $request, RequestHandler $handler): Response {
                $response = $handler->handle($request);
                $stream = $response->getBody();
                $stream->write('CSRF fail');
                return $response->withStatus(400);
            };
        }
        return $this->failureCallable;
    }
}

`

【讨论】:

  • 谢谢@user3294859!
【解决方案2】:

相关位是:

$app->add(Guard::class);

中间件回调的签名已更改。在 Slim/3 中它曾经像 this:

public function __invoke(
    ServerRequestInterface $request,
    ResponseInterface $response,
    callable $next
): ResponseInterface

...然后该方法必须像$next($request, $response) 一样调用$next

在 Slim/4 中是这样的:

public function __invoke(
    ServerRequestInterface $request,
    RequestHandlerInterface $handler
): ResponseInterface

.. 对$handler 的内部调用是$handler-&gt;handle($request)

该库似乎没有针对 Slim/4 进行更新。它在 composer.json 中将 Slim/3 声明为 dev (?) 依赖项,并在 README.md 中提及。也许修复库或在其上编写兼容的包装器并不难,但如果您不熟悉整个生态系统,安装a replacement 可能更容易。

【讨论】:

  • 感谢@Alvaro Gonzalez 的回复!我正在使用 Composer 安装所有软件包。这是否应该使其与 Slim 4 兼容?
  • 抱歉,我忽略了 slim/slim 被声明为 development 依赖项。没有什么能阻止您将它安装在不兼容的 Slim 版本中。顺便说一句,检查user3294859's answer,他只是写了一个包装器!
猜你喜欢
  • 1970-01-01
  • 2022-06-18
  • 2019-01-30
  • 1970-01-01
  • 2019-06-07
  • 2014-09-23
  • 1970-01-01
  • 2014-01-23
  • 2017-01-28
相关资源
最近更新 更多