Symfony / Mercure / JS EventSource 不发送 cookie

Posted

技术标签:

【中文标题】Symfony / Mercure / JS EventSource 不发送 cookie【英文标题】:Symfony / Mercure / JS EventSource don't send cookie 【发布时间】:2021-09-03 01:17:51 【问题描述】:

我已经阻止这个问题 2 天了。我正在尝试为 Mercure 设置身份验证,以便客户可以订阅“私人”集线器。所以我按照 Symfony 和 Mercury 文档中的规定配置了我的环境变量,它们是:

我的应用 Symfony 的 .env:

###> mercure/bundle ###
MERCURE_URL=http://mydemoapp.com:80/.well-known/mercure
MERCURE_PUBLIC_URL=http://mydemoapp.com:80/.well-known/mercure
MERCURE_JWT_SECRET=MySecretKeyJWT
MERCURE_JWT_TOKEN=MyTokenJWT
###< mercure/bundle ###

我的球童档案:


    # Debug mode (disable it in production!)
    debug
    # HTTP/3 support
    experimental_http3


:80

log

route 
    redir / /.well-known/mercure/ui/
    encode gzip

    mercure 
        # Enable the demo endpoint (disable it in production!)
        demo
        # Publisher JWT key
        publisher_jwt MySecretKeyJWT
        # Subscriber JWT key
        subscriber_jwt MySecretKeyJWT
        # CORS
        cors_origins http://127.0.0.1:3005
        # Allow anonymous subscribers (double-check that it's what you want)
        anonymous
        # Enable the subscription API (double-check that it's what you want)
        subscriptions
    

    respond "Not Found" 404

我的容器美居:

  mercure:
    image: dunglas/mercure
    container_name: mercure
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - mercure:/data
    labels:
      - traefik.docker.network=proxy
      - traefik.enable=true
      - traefik.http.routers.mercure.rule=Host(`mydemoapp.com`)
    expose:
      - "80"
    networks:
      - app

这是我的控制器生成授权 cookie 和发布集线器的路由的代码:

我的路线授权:

    /**
     * @Route("/api/v1.0/ms-security/authorization", name="security.index", methods="GET")
     */
    public function index(Authorization $authorization, Request $request): Response
    

        $response = $this->json([
            'message' => 'Your authorization has been generated !',
            'code' => '200',
        ]);

       $response->headers->setCookie($authorization->createCookie($request, ["http://mydemoapp.com:80/api/v1.0/ms-security/23"]));
       return $response;
    

我在集线器上发布的路线(此路线只是一个测试路线,用于了解我的客户是否订阅良好并收到通知):

  /**
     * @Route("/api/v1.0/ms-match/invitations/test", name="invitation.test", methods="GET")
     */
    public function test(HubInterface $hub)
    
       
        $update = new Update("$this->getParameter('base.url')/ms-security/23", json_encode("Hy it's me $this->getUser()->getId() !"), true);
        $hub->publish($update);

        return $this->json(["message" => "ok"]);
    

还有我的javascript


async mounted()
    let data = "phone": "myPhone", "password": "myPassword";
    const resAuth = await fetch("http://mydemoapp.com:80/api/v1.0/ms-security/login", method: "POST", headers:  'Content-Type': 'application/json' , body: JSON.stringify(data));
    const dataAuth = await resAuth.json();
    console.log(dataAuth);

    const res = await fetch("http://mydemoapp.com:80/api/v1.0/ms-security/authorization", method: "GET", headers: 'Authorization': `Bearer $await dataAuth.token`);
    const dataCookie = await res.json();
    console.log(dataCookie)

    const url = new URL('http://mydemoapp.com:80/.well-known/mercure');
    url.searchParams.append('topic', 'http://mydemoapp.com:80/api/v1.0/ms-security/23');

    const eventSource = new EventSource(url, withCredentials: true);
    console.log(eventSource.withCredentials)
    eventSource.onmessage = e => console.log(e.data);
  

当我将路由称为“授权”时,我在响应标头中看到我确实有要发送的 cookie。当我在 JWT.IO 上对其进行解码时,我们可以看到我的 jwt 包含订阅此集线器的信息,但是当我调用我的测试路由时,如果我私下发送此集线器,客户端不会收到通知(在公共场合,一切都很顺利好吧)。所以我的印象是cookies不会发送。

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,但我只能给你一些关于不理想解决方案的提示。 某些浏览器在 localhost 下结合不同端口设置 cookie 存在问题。 Symfony 端口 8000(单独的网络服务器)设置 cookie - 端口 8080 的 UI 不会在 localhost 下显示它,尽管标题中的响应通过“Set-Cookie”传输相应的令牌。另一方面,在生产系统中(UI 和 API 使用相同的端口),一切正常。

作为一种解决方法,我从响应标头中获取了有效令牌(也可以在 jwt.io 上生成)。在设置部分的美居调试工具(http://localhost:3000)中,我选择了 cookie 类型并插入了生成的令牌。如果单击“发现”,则设置 cookie,也可以在 UI 中访问。可能美居在设置 cookie 时使用限制较少的设置。我尝试了许多其他设置,但没有找到直接的解决方案。 使用本地隧道也可能解决此问题。

【讨论】:

以上是关于Symfony / Mercure / JS EventSource 不发送 cookie的主要内容,如果未能解决你的问题,请参考以下文章

使用 Symfony 和 Apache 在生产环境中运行 Mercure | HTTPS 问题

js函数获取ev对象

为什么JS事件函数里面都有一个参数(ev)?

Symfony 4.4控制器容器事件分派器

javascript EV-上载和zip.js

js——ev || window.event,event.srcElement || event.target