symfony动态设置cookie\u域

symfony动态设置cookie\u域,symfony,dynamic,config,Symfony,Dynamic,Config,我有一个可以服务多个域的应用程序。 我在framework.session.cookie\u域中遇到问题 我希望会话保持在子域之间,到目前为止,cookie\u域设置正确 我遇到的问题是,我希望动态设置cookie\u域参数,因为我事先不知道请求来自哪个域 我尝试在AppKernel.php中执行以下操作: $domain=substr($\u服务器['HTTP\u主机'],strpos($\u服务器['HTTP\u主机'],') ini\u集('session.cookie\u doma

我有一个可以服务多个域的应用程序。 我在
framework.session.cookie\u域中遇到问题

  • 我希望会话保持在子域之间,到目前为止,cookie\u域设置正确
  • 我遇到的问题是,我希望动态设置cookie\u域参数,因为我事先不知道请求来自哪个域

    • 我尝试在
      AppKernel.php
      中执行以下操作:
    $domain=substr($\u服务器['HTTP\u主机'],strpos($\u服务器['HTTP\u主机'],')
    
    ini\u集('session.cookie\u domain',$domain)

    • 但它似乎打断了我的会议
  • 我可以为每个域设置多个
    config.yml
    一个,但我希望避免这种情况。

你知道路吗


谢谢

好的,我已经弄明白了

这并不难

我创建了一个自定义sessionStorage,扩展了默认的sessionStorage,并在处理选项的地方做了一个简单的覆盖:在那里我计算了我的cookie\u域并将其传递给parent::函数:

use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

/**
 * DynamicDomainSessionStorage.
 *
 * @author Julien Devouassoud
 */
class DynamicDomainSessionStorage extends NativeSessionStorage
{
     /**
     * setOptions.
     *
     * {@inheritDoc}
     */
    public function setOptions(array $options)
    {   
        if(isset($_SERVER['HTTP_HOST'])){
            $domain = substr($_SERVER['HTTP_HOST'], strpos($_SERVER['HTTP_HOST'], '.'));

            $options["cookie_domain"] = $domain;
        } 



        return parent::setOptions($options);
    }
}
别忘了:

•将您的类声明为服务

•将此服务设置为存储

•设置保存路径,否则cookie\u域似乎无法工作(中断会话)

•我也设定了一个“名称”,但我不认为这是必要的

•代码
config.yml

#...
framework:
    #...
    session:
         storage_id: v3d.session.storage.dynamic_domain
         save_path: %kernel.root_dir%/cache/var/sessions
         name: SFSESSID

services
    v3d.session.storage.dynamic_domain:
        class: V3d\Bundle\ApplicationBundle\Services\DynamicDomainSessionStorage

我也有类似的情况。这是一个多租户的网站,有学区和学校。每个地区和学校都有自己的URL,如下所示:

  • school-1.district-1.example.com
  • school-2.district-1.example.com
  • school-1.district-2.example.com
我希望用户能够访问一个单一的登录一个地区的所有学校。因此,我需要cookie位于地区级别

这是我的会话存储服务

namespace AppBundle\Services;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

class MySessionStorage extends NativeSessionStorage
{
    public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null, RequestStack $requestStack)
    {
        $host = $requestStack->getMasterRequest()->getHost();
        $options['cookie_domain'] = substr($host, strpos($host, '.') + 1);

        parent::__construct($options, $handler, $metaBag);
    }
}
In services.yml

mySessionStorage:
    class: AppBundle\Services\MySessionStorage
    arguments: [%session.storage.options%, @session.handler, @session.storage.metadata_bag, @request_stack]
cookieFix:
    class: AppBundle\Listeners\CookieFix
    arguments: [@request_stack]
    tags:
        - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse, priority: -100 }
在框架下的config.yml中:

session:
    handler_id: session.handler.native_file
    storage_id: mySessionStorage
请注意,在标准Symfony安装中,默认情况下处理程序的id为null(~)。需要将其设置为某个值,服务才能接收非null@session.handler

会话cookie就是这样,但我需要更改的另一个cookie是“记住我”cookie。您可以在config.yml中将域设置为常量,但我需要它依赖于主机。也许我遗漏了一些东西,但我找不到在安全系统中动态执行的方法。MemberMefactory是直接实例化的,而不是通过配置。我的解决方案是侦听kernel.response并在发送cookie之前替换它

namespace AppBundle\Listeners;

use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class CookieFix
{
    private $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function onKernelResponse(FilterResponseEvent $event)
    {
        $response = $event->getResponse();
        $cookies = $response->headers->getCookies();
        $rMe = null;

        foreach($cookies as $cookie) {
            /** @var \Symfony\Component\HttpFoundation\Cookie $cookie */
            if ($cookie->getName() == 'REMEMBERME') {
                $rMe = $cookie;
                break;
            }
        }

        if ($rMe !== null) {
            $host = $this->requestStack->getMasterRequest()->getHost();
            $newDomain = substr($host, strpos($host, '.') + 1);

            $response->headers->removeCookie($rMe->getName());
            $response->headers->setCookie(new Cookie($rMe->getName(), $rMe->getValue(), $rMe->getExpiresTime(), $rMe->getPath(), $newDomain));
        }
    }
}
我可能应该尝试从配置中获取cookie名称

In services.yml

mySessionStorage:
    class: AppBundle\Services\MySessionStorage
    arguments: [%session.storage.options%, @session.handler, @session.storage.metadata_bag, @request_stack]
cookieFix:
    class: AppBundle\Listeners\CookieFix
    arguments: [@request_stack]
    tags:
        - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse, priority: -100 }

-100优先级确保它在创建cookie的侦听器之后运行。

我还必须将它添加到会话存储构造中:`if(!$masterRequest=$requestStack->getMasterRequest()){return;}$host=$masterRequest->getHost()`