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

Trello令牌认证异常:无法提取弹窗中的令牌并完成后续操作

Trello令牌认证异常:无法提取弹窗中的令牌并完成后续操作

看起来你遇到的核心问题是浏览器同源策略限制导致的——你的主页面和Trello的授权弹窗属于不同域名,直接访问popup.document会被浏览器拦截,这就是为什么你的代码明明检测到了正确的URL,却始终拿不到<pre>里的令牌,也没法关闭弹窗。

我帮你分析下问题根源,再给几个可行的解决方案:


问题根源:跨域访问被拦截

你代码里的popup.document.querySelector('pre')这一行会触发浏览器的跨域安全限制,因为Trello的域名和你的应用域名不一致,浏览器不允许主页面直接读取其他域名页面的DOM内容。虽然你加了try/catch,但可能没注意到控制台里的跨域错误,导致整个提取令牌的逻辑根本没执行。


解决方案1:用Trello官方JS SDK(最省心)

Trello官方提供了专门的JS SDK,已经帮你处理好了跨域、弹窗通信这些坑,直接用就行:

// 先在页面引入Trello SDK(替换成你的APP_KEY)
// <script src="https://trello.com/1/client.js?key=YOUR_TRELLO_APP_KEY"></script>

async authenticateTrello() {
  Trello.authorize({
    type: 'popup',
    name: 'TrelloPlanner',
    scope: { read: true, write: true },
    expiration: '1hour',
    success: (token) => {
      console.log('Token received:', token);
      this.trelloToken = token;
      sessionStorage.setItem('trelloToken', token);
      this.checkAuth();
    },
    error: () => {
      console.error('Failed to authenticate with Trello');
    }
  });
}

这种方式不需要自己处理弹窗轮询和DOM读取,官方SDK会自动完成令牌提取和弹窗关闭,可靠性最高。


解决方案2:用postMessage+重定向替代DOM读取

如果你不想用官方SDK,可以通过指定重定向地址+postMessage跨域通信的方式来实现:

步骤1:修改授权URL,添加redirect_uri参数

把授权URL指向你自己的页面(必须和主页面同域名),这样Trello授权成功后会跳转到你的页面,避免跨域:

const authUrl = `https://trello.com/1/authorize?expiration=1hour&name=TrelloPlanner&scope=read,write&response_type=token&key=${TRELLO_APP_KEY}&redirect_uri=${window.location.origin}`;

步骤2:在你的页面添加令牌监听逻辑

当Trello跳回你的页面时,URL里会带上token参数,我们可以把这个令牌通过postMessage发送给主窗口:

// 在页面初始化时检查URL中的令牌
window.addEventListener('load', () => {
  const urlParams = new URLSearchParams(window.location.search);
  const token = urlParams.get('token');
  if (token && window.opener) {
    // 向主窗口发送令牌消息
    window.opener.postMessage(
      { type: 'TRELLO_AUTH_TOKEN', token: token },
      window.location.origin
    );
    // 关闭弹窗
    window.close();
  }
});

步骤3:修改主页面的认证逻辑,监听postMessage

把原来的轮询DOM逻辑改成监听弹窗发送的消息:

async authenticateTrello() {
  const authUrl = `https://trello.com/1/authorize?expiration=1hour&name=TrelloPlanner&scope=read,write&response_type=token&key=${TRELLO_APP_KEY}&redirect_uri=${window.location.origin}`;

  const token = await new Promise((resolve) => {
    const popup = window.open(authUrl, 'Trello Auth', 'width=800,height=800');
    
    // 监听来自弹窗的消息
    const messageHandler = (event) => {
      // 验证消息来源,确保安全
      if (event.origin !== window.location.origin) return;
      if (event.data.type === 'TRELLO_AUTH_TOKEN') {
        resolve(event.data.token);
        window.removeEventListener('message', messageHandler);
      }
    };
    window.addEventListener('message', messageHandler);

    // 监听弹窗意外关闭的情况
    const interval = setInterval(() => {
      if (popup.closed) {
        clearInterval(interval);
        window.removeEventListener('message', messageHandler);
        resolve(null);
      }
    }, 500);
  });

  if (token) {
    console.log('Token received:', token);
    this.trelloToken = token;
    sessionStorage.setItem('trelloToken', token);
    this.checkAuth();
  } else {
    console.error('Failed to authenticate with Trello');
  }
}

最后检查建议

如果你想验证原来的问题,可以打开浏览器控制台,执行认证操作时看看有没有跨域相关的错误提示——这应该就是你之前代码失效的直接原因。

备注:内容来源于stack exchange,提问作者leefbrie

火山引擎 最新活动