【问题标题】:Request headers bag is missing Authorization header in Symfony 2?Symfony 2 中的请求标头包缺少授权标头?
【发布时间】:2012-08-12 23:49:47
【问题描述】:

我正在尝试在 Symfony 2 中实现 custom authentication provider。我正在使用 Fiddler 发送测试请求并打印所有标头服务器端;好吧,Authorization 标头不见了。

我做错了吗?

GET /RESTfulBackend/web/index.php HTTP/1.1
Authorization: FID 44CF9590006BF252F707:jZNOcbfWmD/
Host: localhost
User-Agent: Fiddler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

监听器只打印标题并退出:

class HMACListener implements ListenerInterface
{
    private $securityContext;

    private $authenticationManager;

    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        print_r($request->headers->all()); 
        die();
     }
}

响应缺少Authorization 标头:

Array
(
    [host] => Array
        (
            [0] => localhost
        )
    [user-agent] => Array
        (
            [0] => Fiddler
        )
    [accept] => Array
        (
            [0] => text/html,application/xhtml+xml,application/xml
        )
    [accept-language] => Array
        (
            [0] => it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
        )
)

【问题讨论】:

标签: php http symfony http-headers fiddler


【解决方案1】:

您必须将此代码添加到 virtualhost 标记

如果你把它放在目录标签里,它不会起作用。

    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

【讨论】:

  • 这对我来说就像一个魅力,你能解释一下它的作用吗?
  • 谢谢你的工作,但可能有问题。即使传入请求中不存在授权标头字段,它看起来也已创建。这不应该是行为
  • 是的,它正在创建一个授权头字段,即使请求中没有,有什么想法吗?
  • 我在 .htaccess 中添加了以下内容:RewriteCond %{HTTP:Authorization} .+
  • 这个和here的答案一模一样。
【解决方案2】:

Akambi 的答案对我不起作用,但在 php 网站上找到了这个答案:

“CGI/FastCGI Apache 下缺少授权标头的解决方法:

SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

现在,如果客户端发送 Authorization 标头,PHP 应该自动声明 $_SERVER[PHP_AUTH_*] 变量。”

感谢 derkontrollfreak+9hy5l!

【讨论】:

  • 谢谢。你知道为什么没有发送标头吗?
  • 应用了这个修复,但它仍然没有响应我脚本中的 401 标头。
  • 这是唯一有效的解决方案,RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 的一个无效
  • 通过在 VirtualHost 配置文件中添加它对我有用。它在 .htaccess 中也应该可以正常工作,只需确保在请求到达您的应用之前没有代理、容器等。
【解决方案3】:

经过验证的解决方案当时对我有用,可以通过 Authorization 标头。但是,当传入请求中没有 Authorization 标头时,它会生成一个空的 Authorization 标头。我就是这样解决的:

RewriteEngine On
RewriteCond %{HTTP:Authorization} .+
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

【讨论】:

    【解决方案4】:

    在编写带有自定义 Authorization 标头的公共 API 时,我遇到了同样的问题。为了修复HeaderBag,我使用了一个监听器:

    namespace My\Project\Frontend\EventListener;
    
    use Symfony\Component\HttpFoundation\HeaderBag;
    
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    
    /**
     * Listener for the REQUEST event. Patches the HeaderBag because the
     * "Authorization" header is not included in $_SERVER
     */
    class AuthenticationHeaderListener
    {
        /**
         * Handles REQUEST event
         *
         * @param GetResponseEvent $event the event
         */
        public function onKernelRequest(GetResponseEvent $event)
        {
            $this->fixAuthHeader($event->getRequest()->headers);
        }
        /**
         * PHP does not include HTTP_AUTHORIZATION in the $_SERVER array, so this header is missing.
         * We retrieve it from apache_request_headers()
         *
         * @param HeaderBag $headers
         */
        protected function fixAuthHeader(HeaderBag $headers)
        {
            if (!$headers->has('Authorization') && function_exists('apache_request_headers')) {
                $all = apache_request_headers();
                if (isset($all['Authorization'])) {
                    $headers->set('Authorization', $all['Authorization']);
                }
            }
        }
    }
    

    并将其绑定到服务定义中的kernel.request:

    services:
      fix_authentication_header_listener:
        class: My\Project\Frontend\EventListener\AuthenticationHeaderListener
        tags:
          - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 255 }
    

    【讨论】:

    • 请注意,您需要安装 PHP 的 Apache 扩展,才能使用 apache_request_headers 函数。
    【解决方案5】:

    Authorization 标头用于http basic authentication,如果格式无效,则被 apache 丢弃。尝试使用其他名称。

    【讨论】:

    • 谢谢。例如,Amazon S3 如何使用它? s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
    • 好吧,如果你看到 Apache 实现,它期望请求令牌是 base_64 编码的字符串,在服务器端它 base64_decode 字符串并设置 PHP_AUTH_USER 和 PHP_AUTH_PW 服务器变量。如您所见,实现是特定于服务器的。因此,Amazon S3 Web 服务器以不同的方式实现了该方案。
    • 那你会建议什么?使用 apache_request_headers() (特定于 apache)还是使用自定义标头?
    • 您可以制作一个 apache 模块,使您的身份验证方案符合 http 基本身份验证。例如检查this 模块。或者您可以使用自定义标题,例如 X-FID-Authorization.
    • AFAIK Apache 将接受任何格式的授权标头。 PHP 会丢弃除有效的 Basic 或 Digest 标头之外的任何内容。
    【解决方案6】:

    另一个适用于 Apache 2.4 的选项是在相关的 <Directory> 上下文中设置 CGIPassAuth 选项,如下所示:

    CGIPassAuth On
    

    根据文档,它从 Apache 2.4.13 开始可用。

    【讨论】:

    • 这对我有用。否则 getallheaders 和 $_SERVER 中都缺少 Authorization 标头
    【解决方案7】:

    另一种解决方案是将您的 PHP 处理程序更改为以 Apache Module 而不是 CGI application 运行 PHP。

    【讨论】:

    • 虽然不是一个好的解决方案,因为它作为模块比作为 CGI 慢。开发过程中缓存和日志文件夹的权限也存在问题。
    • @Jorj“问题”你能说得更具体点吗?我敢打赌,这只是配置问题。这是一个可行的解决方案。从来没有说过这是“最好的”。这是一个见仁见智的问题..
    • 当然,会发生这种情况:作为 unix 机器上的开发人员,您会在您的用户下创建文件,对吗?然后,您将从控制台启动一些命令,这些命令将在缓存和日志文件夹中创建文件。如果 PHP 在 Apache 中被配置为模块,它将与 Apache 的用户一起运行,即“www”或“nobody”或类似的东西。结果,它会尝试覆盖您在缓存和日志文件夹中创建的文件,并且会抛出错误,因为它们属于另一个所有者。当然,也有解决方法,但仍然是一个额外的头痛。
    【解决方案8】:

    我们应该在服务器端授权这个header“Authorization”,

    它也可以简单地用 nelmioCorsBundle 完成 nelmio_cors: defaults: allow_credentials: false allow_origin: [] allow_headers: [] allow_methods: [] expose_headers: [] max_age: 0 hosts: [] origin_regex: false forced_allow_origin_value: ~ paths: '^/api/': allow_origin: ['*'] allow_headers: ['Authorization']

    【讨论】:

      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 2018-07-17
      • 2017-12-19
      • 2020-11-12
      • 1970-01-01
      • 2012-10-27
      • 2011-05-04
      相关资源
      最近更新 更多