Php 覆盖symfony2中GET请求的HTTP方法

Php 覆盖symfony2中GET请求的HTTP方法,php,symfony,Php,Symfony,我正在阅读以下URL上的“用_方法伪造方法”部分: 经过一些实验,我意识到文档要么不清楚,要么不准确。 如果浏览器使用POST(而不是GET)发出请求,则只能使用\u method参数覆盖HTTP方法 Symfony\Component\HttpFoundation\Request public function getMethod() { if (null === $this->method) { $this->method = s

我正在阅读以下URL上的“用_方法伪造方法”部分:

经过一些实验,我意识到文档要么不清楚,要么不准确。 如果浏览器使用POST(而不是GET)发出请求,则只能使用\u method参数覆盖HTTP方法

Symfony\Component\HttpFoundation\Request

public function getMethod()
    {
        if (null === $this->method) {
            $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));

            if ('POST' === $this->method) {
                if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
                    $this->method = strtoupper($method);
                } elseif (self::$httpMethodParameterOverride) {
                    $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
                }
            }
        }

        return $this->method;
    }
在我们的应用程序中,我们希望覆盖GET请求的HTTP方法,因为我们使用的是JSONP。 在我们的例子中,这不是一个安全问题,因为请求是使用CSRF令牌签名的

我在这里的“覆盖请求”部分找到了解决方案:

这将涉及生成Symfony\Component\HttpFoundation\Request的子类,覆盖getMethod()方法,并使用Request::setFactory()进行设置

我的问题是:

我唯一可以看到的地方是app.php/app_dev.php/app_test.php。例如:

require_once __DIR__.'/../app/AppKernel.php';

$kernel = new AppKernel($env, $is_debug);
$kernel->loadClassCache();

// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter
//Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
这是个合适的地方吗

我查看了内核事件,例如kernel.request,但现在看来,该事件太晚了,无法发挥作用:

“1)kernel.request事件 典型用途:向请求添加更多信息、初始化部分系统或返回响应(如拒绝访问的安全层)。”


如有任何建议,将不胜感激。谢谢。

要覆盖symfony中的HTTP方法,并不难,首先将参数方法添加到路由中:

blog_update:
    path:     /blog/{slug}
    defaults: { _controller: AcmeDemoBundle:Blog:update }
    methods:   [PUT]
接下来,根据您使用的symfony的版本,启用Http方法参数覆盖,下面是如何做到这一点:(来自symfony doc)

此处显示的_方法功能在Symfony 2.2中默认禁用,在Symfony 2.3中默认启用。要在Symfony 2.2中对其进行控制,必须在处理请求之前(例如在前端控制器中)调用Request::enableHttpMethodParameterOverride。在Symfony 2.3中,使用http方法覆盖选项。

现在,如果您正在使用symfony的FormBuilder,它应该添加一个名为“\u method”的隐藏输入,或者如果您不使用symfony的form builder,您可以自己添加它


下面是完整的文档:

要在symfony中启用HTTP方法覆盖,您应该在config.yml中定义HTTP方法覆盖

framework:
    http_method_override: true

覆盖请求对象 对于那些对重写
请求
基类感兴趣的人

实际上,文件中有一个错误,我将为此发送一份PR


以下(参见您的示例)不正确:

use Symfony\Component\HttpFoundation\Request;

Request::setFactory(function (
    array $query = array(),
    array $request = array(),
    array $attributes = array(),
    array $cookies = array(),
    array $files = array(),
    array $server = array(),
    $content = null
) {
    return SpecialRequest::create(
        $query,
        $request,
        $attributes,
        $cookies,
        $files,
        $server,
        $content
    );
});

$request = Request::createFromGlobals();
以下是正确的:

use Symfony\Component\HttpFoundation\Request;

Request::setFactory(function (
    array $query = array(),
    array $request = array(),
    array $attributes = array(),
    array $cookies = array(),
    array $files = array(),
    array $server = array(),
    $content = null
) {
    return new SpecialRequest(
        $query,
        $request,
        $attributes,
        $cookies,
        $files,
        $server,
        $content
    );
});

$request = Request::createFromGlobals();

你能看出区别吗

  • 请查看并签名

此问题应适用于Symfony 2.3及以上版本。从2.4开始,您可以调整用于创建请求对象的工厂。否则我认为你走对了方向。但要仔细考虑你要完成的任务。这种方法是为了克服浏览器的限制。如您所提议的那样滥用它将完全搞糟各种http缓存问题。我想你最终会后悔走这条路。嗨,蒂约,我试过这两种方法。此解决方案仅在浏览器向服务器发出POST请求时有效(请参阅上面的第一段代码摘录)。我还需要一个能够处理GET请求的解决方案。澄清一下,POST请求可以使用_方法转换为任何其他方法,但GET请求不能。我恐怕没有办法这样做,因为symfony说这只适用于POST,就像如果方法是GET,他们不会检查是否要覆盖该方法一样。@JaySheth给你,从symfony文档中:
static public enableHttpMethodParameterOverride()启用对_method请求参数的支持,以确定预期的HTTP方法。请注意,启用此功能可能会导致代码中出现CSRF问题。检查您是否在需要时使用CSRF令牌。只有当真正的HTTP方法是POST时,才能覆盖HTTP方法。
use Symfony\Component\HttpFoundation\Request;

Request::setFactory(function (
    array $query = array(),
    array $request = array(),
    array $attributes = array(),
    array $cookies = array(),
    array $files = array(),
    array $server = array(),
    $content = null
) {
    return new SpecialRequest(
        $query,
        $request,
        $attributes,
        $cookies,
        $files,
        $server,
        $content
    );
});

$request = Request::createFromGlobals();