与 Web 小部件通信 - Meteor、React、Node

2024-03-02

我正在构建一个聊天仪表板和小部件,客户应该能够将小部件放入他们的页面中。一些类似的例子是Intercom http://www.intercom.com or Drift http://drift.com.

目前,“主”应用程序是用 Meteor.js 编写的(它的前端是 React)。我写了一个<Widget />组件并将其扔进一个/widget目录。在这个目录中,我还有一个index.jsx文件,其中仅包含以下内容:

import React from 'react';

import ......

ReactDOM.render(
  <Widget/>,
  document.getElementById('widget-target')
);

然后我设置了一个 webpack 配置,入口点为index.jsx当 webpack 运行时会输出一个bundle.js在公共目录中。

然后只需包含一个即可将其包含在另一个页面上script and div:

<script src="http://localhost:3000/bundle.js" type="text/javascript"></script>
<div id="widget-target"></div>

几个问题:

  1. 这个实现有什么问题吗?他们有什么安全问题需要注意吗?前面链接的两个示例似乎都以一种或另一种形式使用了 iframe。
  2. 与我的主要流星应用程序通信的最佳方式是什么? REST API?使用 Socket.io 发出事件?该小部件是一个聊天小部件,因此我需要来回发送消息。
  3. 如何为用户和小部件实现某种唯一标识符/用户身份验证?目前,该小部件已预编译。

1 这个实现有什么问题?他们有什么安全问题需要注意吗?前面链接的两个示例似乎都以一种或另一种形式使用了 iframe。

正如 @JeremyK 提到的,在 iFrame 中你会更安全。话虽如此,许多第三方(Facebook、GA 等)都在使用中间路线,包括 Intercom:

  • 要求用户将您的捆绑代码集成到他们的网页中。然后,您需要确保不会在他们的网站上引入安全漏洞。这段代码将做两件事:
  • 负责设置一个 iframe,您的服务的主要部分将在其中发生。您可以对其进行定位、设置样式等。这可以确保 iframe 中发生的所有逻辑都是安全的,并且您不会暴露。
  • 使用窗口消息传递在您的客户网页和 iframe 之间公开一些 API。
  • 然后,主代码(iframe 代码)由第一个脚本异步加载,并且不包含在其中。

例如,Intercom 要求客户在其页面上包含一些脚本:https://developers.intercom.com/docs/single-page-app#section-step-1-include-intercom-js-library https://developers.intercom.com/docs/single-page-app#section-step-1-include-intercom-js-library那相当小(https://js.intercomcdn.com/shim.d97a38b5.js https://js.intercomcdn.com/shim.d97a38b5.js)。这会加载设置 iFrame 并公开的额外代码他们的API https://developers.intercom.com/docs/intercom-javascript这将使与 iFrame 的交互变得容易,例如关闭它、设置用户属性等。

2 与我的主要流星应用程序通信的最佳方式是什么? REST API?使用 Socket.io 发出事件?该小部件是一个聊天小部件,因此我需要来回发送消息。

你有三个选择:

  • 将您的小部件构建为整个 Meteor 应用程序。这将增加需要加载的代码的大小。作为额外代码的交换,您可以通过 Meteor API 与后端进行通信,例如流星召唤 https://docs.meteor.com/api/methods.html#Meteor-call,获取所有数据的反应性(例如,如果您通过主 Meteor 应用程序向用户发送响应,则响应将在客户端上弹出,只要它们位于同一数据库上,则无需执行任何操作(无需在同一台服务器上)),以及乐观的 UI。简而言之,您已经拥有 Meteor 提供的所有功能,并且与您现有的后端(我认为是 Meteor)集成可能会更容易。
  • 不包括流星。由于您正在构建聊天应用程序,因此您可能需要socket.io通过传统的 REST API。当然你可以混合使用两者
  • Use 流星DDP https://www.npmjs.com/package/ddp。 (它有点像 socket.io,但对于 Meteor。Meteor 应用程序使用它来处理对服务器的所有请求)这将包含比完整 Meteor 更少的内容,并且可能比 REST API 更容易集成到您的 Meteor 后端/socket.io,并且将对完整的 Meteor 进行一些额外的工作。

3 如何为用户和小部件实现某种唯一标识符/用户身份验证?

这部分可能应该在客户网站上(相对于您的 iframe 中)做一些工作,以便您可以在他的页面上设置 cookie,并将该数据发送到您的 iframe,该 iframe 将与您的服务器通信并识别用户。无论你使用artwells:accounts-guest(这是基于meteor:accounts-base) 将取决于您是否决定将 Meteor 包含在您的 iframe 中。

如果您的 iframe 中没有 Meteor,您可以执行以下操作:

  • 只需在服务器上执行即可自行处理用户创建

.

const token = createToken();
Users.insert({ tokens: [token] });
// send the token back to your iframe
// and set is as a cookie on your customer website
  • 然后对于您的服务器的每次调用,在您的 iframe 上:

.

let token;
const makeRequest = async (request) => {
    token = token || getCookieFromCustomerWebsite();
    // pass the token to your HTTP / socket.io / ... request.
    // in the header of whatever
    return await callServer(token, request);
};
  • 服务器中有一个设置用户的中间件。我的看起来像:

.

const loginAs = (userId, cb) => {
  DDP._CurrentInvocation.withValue(new DDPCommon.MethodInvocation({
    isSimulation: false,
    userId,
  }), cb);
};

// my middleware that run on all API requests for a non Meteor client
export const identifyUserIfPossible = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return next();
  }
  const user = Users.findOne({ tokens: token });
  if (!user) {
    return next();
  }

  loginAs(user._id, () => {
    next();
    // Now Meteor.userId() === user._id from all calls made on that request
    // So you can do Meteor.call('someMethod') as you'd do on a full Meteor stack
  });
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

与 Web 小部件通信 - Meteor、React、Node 的相关文章

随机推荐