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

Orb*_*bit 6 javascript node.js meteor reactjs webpack

我正在构建一个聊天仪表板和小部件,客户应该可以将小部件放入他们的页面.一些类似的例子是IntercomDrift.

目前,"main"应用程序是用Meteor.js编写的(它的前端是React).我编写了一个<Widget />组件并将其抛入/widget目录.在这个目录里面,我还有一个index.jsx文件,它只包含以下内容:

import React from 'react';

import ......

ReactDOM.render(
  <Widget/>,
  document.getElementById('widget-target')
);
Run Code Online (Sandbox Code Playgroud)

然后,我设置了一个带有入口点的webpack配置,index.jsx当webpack运行时,bundle.js在公共目录中吐出一个.

然后,只需包含一个script和,就可以将其包含在另一个页面中div:

<script src="http://localhost:3000/bundle.js" type="text/javascript"></script>
<div id="widget-target"></div>
Run Code Online (Sandbox Code Playgroud)

几个问题:

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

Gui*_*uig 7

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

正如@JeremyK所说,你在iFrame中更安全.话虽如此,许多第三方(Facebook,GA,......)正在使用中间路线,包括对讲:

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

例如,Intercom要求客户在他们的页面上添加一些脚本:https://developers.intercom.com/docs/single-page-app#section-step-1-include-intercom-js-library,这个脚本非常小(https: //js.intercomcdn.com/shim.d97a38b5.js).这会加载额外的代码,用于设置iFrame并公开其API,以便于与iFrame交互,例如关闭它,设置用户属性等.

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

你有三个选择:

  • 将您的小部件构建为整个Meteor应用程序.这将增加需要加载的代码的大小.作为额外代码的交换,您可以通过Meteor API(如Meteor.call)与您的后端进行通信,获得所有数据的反应性(例如,如果您通过主Meteor应用程序向用户发送响应,则响应会弹出在客户端没有工作要做,只要他们在同一个数据库上(不需要在同一台服务器上))和乐观的用户界面.简而言之,这就是Meteor在这里提供的所有内容,并且可能更容易与现有的后端集成,我假设是Meteor.
  • 不包括Meteor.由于您正在构建聊天应用程序,因此您可能需要socket.io通过传统的REST API.当然,你可以混合使用两者
  • 使用Meteor DDP.(它有点像socket.io,但对于Meteor.流星应用程序使用它来处理服务器的所有请求)这将包括更少的东西,完整的Meteor并且可能更容易集成到您的Meteor后端而不是REST API/socket.io,以及将在整个流星上做一些额外的工作.

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

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

如果您的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
Run Code Online (Sandbox Code Playgroud)
  • 然后,对于您的服务器的每次调用,在您的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);
};
Run Code Online (Sandbox Code Playgroud)
  • 在服务器中有一个设置用户的中间件.我看起来像:

.

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
  });
};
Run Code Online (Sandbox Code Playgroud)


小智 2

要求您的客户像这样嵌入您的代码不符合“设计安全”的原则。

从他们的角度来看,您要求他们将预捆绑的代码嵌入到他们的网站中,从而使他们的网站面临您的代码中存在的任何隐藏的安全风险(无意或故意的恶意),这些风险可以不受限制地访问其网站的 DOM、本地存储, ETC。

这就是为什么使用iframe是在网站中嵌入第三方内容的首选方法,因为该内容是从其主机网站的其余部分沙箱化的。

此外,遵循“最小权限”的安全原则,他们(根据您的指导/示例)可以sandbox在 iframe 上设置属性,并通过白名单明确锁定小部件将拥有的权限。

将您的小部件加载到 an 中iframe还可以让您更灵活地与服务器进行通信。现在这可能是一个普通的 Meteor 客户端,使用 Meteor 的 ddp 与您的服务器进行通信。您的其他建议也是可能的。

用户身份验证/身份验证取决于您的系统的详细信息。这可能包括使用Meteor 帐户,它可以为您提供密码或社交身份验证解决方案。或者您可以尝试匿名帐户解决方案,例如artwells:accounts-guest

html5rocks 关于沙盒 iframe 的文章