You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

跨端口弹窗如何向父窗口设置localStorage?

问题根源

你遇到的报错是浏览器同源策略在搞事情!3001端口的CRA前端和3000端口的Rails服务器属于不同的源(端口不同即跨域),浏览器会严格限制跨域窗口之间直接访问彼此的DOM、localStorage等敏感资源,所以直接调用window.opener.localStorage.setItem肯定会被拦截。

可行解决方案:使用postMessage跨域通信

这是跨域窗口间安全传递数据并触发父窗口操作的标准方案,分两步就能实现:

1. 父窗口(3001端口的CRA)监听消息

在CRA项目的入口文件(比如src/index.js)或者需要接收消息的组件里,添加消息监听逻辑,先验证来源再操作localStorage:

// 父窗口代码
window.addEventListener('message', (event) => {
  // 务必验证消息来源,只处理信任的3000端口请求
  if (event.origin !== 'http://localhost:3000') return;

  // 根据消息类型执行对应逻辑
  if (event.data.type === 'SET_AUTHORIZATION_TOKEN') {
    localStorage.setItem('authorization', event.data.token);
    // 可选:这里可以触发页面刷新、状态更新等后续操作
  }
});

2. 弹窗(3000端口的Rails页面)发送消息

在Rails的视图文件里,把原来的代码替换成向父窗口发送消息的逻辑:

# Rails视图中的代码
<<-HEREDOC
  window.opener.postMessage(
    { 
      type: 'SET_AUTHORIZATION_TOKEN', 
      token: 'Bearer #{@jwt_token}' 
    },
    'http://localhost:3001' // 指定父窗口的源,确保消息只发送给信任的窗口
  );
  window.close();
HEREDOC
关键注意事项
  • 必须验证消息来源:永远不要跳过event.origin的校验,否则可能被恶意网站利用进行XSS攻击。
  • 明确指定目标源postMessage的第二个参数尽量写具体的源(比如http://localhost:3001),而不是*,避免消息泄露给无关窗口。

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

火山引擎 最新活动