You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 6 + Mercure:如何验证用户的主题订阅权限?

解决Mercure主题订阅权限控制问题

Mercure的JWT并非仅用于Hub连接授权,还能通过subscribe和publish声明精确控制用户可访问的主题,这正是解决你问题的核心。以下是具体实现步骤:

1. 生成带主题权限的Mercure JWT

在Symfony中,动态生成包含当前用户专属主题权限的JWT,替代全局无限制的JWT。示例代码:

use Firebase\JWT\JWT;

// 获取当前用户登录名
$userLogin = $this->getUser()->getLogin();
$allowedTopic = "/notifications/{$userLogin}";

// 构造JWT payload,限制订阅和发布权限
$payload = [
    'mercure' => [
        'subscribe' => [$allowedTopic],
        'publish' => [$allowedTopic],
        'exp' => time() + 3600, // 设置1小时过期,降低泄露风险
    ],
];

// 用Mercure密钥生成JWT
$jwt = JWT::encode($payload, $_ENV['MERCURE_JWT_SECRET'], 'HS256');

// 将JWT传递给模板(比如通过控制器参数)

2. 传递权限JWT到Twig的mercure函数

修改Twig代码,将生成的带权限JWT传入mercure函数,确保生成的订阅URL携带权限验证信息:

<li id="notifications-bell-dropdown" 
    data-mercure-notification="{{ mercure(
        '/notifications/' ~ app.user.login, 
        { 
            publish: '/notifications/' ~ app.user.login, 
            subscribe: '/notifications/' ~ app.user.login,
            jwt: jwtToken 
        }
    )|escape('html') }}" 
    class="dropdown">
</li>

3. 配置Mercure Hub强制验证权限

启动Mercure Hub时,指定JWT密钥开启权限验证,此时Hub会检查JWT中的subscribe声明,拒绝未授权的主题订阅:

mercure run --jwt-key='你的MERCURE_JWT_SECRET值' --addr='localhost:3000'

4. 后端发布时的额外验证(可选)

在发布通知的服务中,添加逻辑确保只有合法主体能向目标主题发布内容,比如:

public function publishNotifications(string $login, string $message): void
{
    // 可选:验证当前用户是否有权向该login的主题发布(比如系统用户或相关关联用户)
    // if (!$this->isAuthorizedToPublish($login)) {
    //     throw new AccessDeniedException();
    // }

    $update = new Update(
        "/notifications/" . $login,
        $message,
        true
    );

    $this->hub->publish($update);
}

关键说明

之前的实现风险在于:使用的Mercure JWT未包含主题权限限制,导致用户可通过修改订阅URL中的主题路径,用自己的JWT监听他人通知。通过在JWT中明确subscribe允许的主题列表,Mercure Hub会直接拦截不符合权限的订阅请求,从根源解决问题。

额外安全建议:

  • 全程使用HTTPS,防止JWT被窃听
  • 缩短JWT过期时间,降低泄露后的影响范围
  • 前端代码避免暴露其他用户的主题路径

内容的提问来源于stack exchange,提问作者JulienM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:01:00