与一个Web小部件 – meteor,反应,节点通信

我正在构build一个聊天仪表板和小部件,客户应该能够将小部件放入其页面。 一些类似的例子是Intercom或者Drift 。

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

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

然后我在index.jsx设置一个入口点的webpackconfiguration,当运行bundle.js在公共目录下将bundle.js吐出来。

这可以包含在另一个页面,只需包含一个scriptdiv

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

几个问题:

  1. 这个实现有什么问题? 他们的安全问题是否需要注意? 前面链接的例子似乎都以某种forms使用iframe。
  2. 什么是与我的主要meteor应用程序沟通的最佳方式? 一个REST API? 用Socket.io发送事件? 小部件是一个聊天小部件,所以我需要来回发送消息。
  3. 我怎样才能为用户和小部件实现某种唯一的标识符/用户身份validation? 目前,该小部件是预编译的。

1这个实现有什么问题? 他们的安全问题是否需要注意? 前面链接的例子似乎都以某种forms使用iframe。

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

  • 要求用户将你的捆绑代码整合到他们的网页中。 然后由您来确保您不在他们的网站上引入安全漏洞。 这段代码将做两件事:
  • 照顾设置一个iframe,其中你的服务的主要部分将发生。 你可以定位,风格等。这确保了iframe中的所有逻辑是安全的,你不会暴露。
  • 在客户网页和iframe之间使用窗口消息传递一些API。
  • 主代码(iframe代码)由第一个脚本asynchronous加载,而不包含在其中。

例如,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的交互变得容易,例如closures它,设置用户属性等。

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

你有三个select:

  • 将您的小部件构build为整个Meteor应用程序。 这将增加需要加载的代码的大小。 为了交换额外的代码,你可以通过Meteor API与你的后端进行通信,比如Meteor.call ,获得所有数据的react native(例如,如果你通过主Meteor应用程序向用户发送响应,响应将会popup只要他们在同一个数据库(不需要在同一台服务器上),就可以在客户端上完成任务,而且乐观的用户界面。 简而言之,你已经知道了Meteor在这里提供的所有东西,并且可能会更容易地与我认为是Meteor的现有后端集成。
  • 不要包括meteor。 由于您正在构build聊天应用程序,因此您可能需要使用传统REST API上的socket.io 。 当然,你可以混合使用两者
  • 使用meteorDDP 。 (它与socket.io类似,但是对于Meteor而言,Meteor应用程序会将所有请求用于服务器)这将包含更less的东西,可能比整个Meteor更容易集成到Meteor后端,而不是REST API / socket.io ,并且会在整个Meteor上做一些额外的工作。

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

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

如果你的iframe中没有Meteor,你可以这样做:

  • 自己处理用户创build,只需在您的服务器上进行

 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 }); }; 

请求您的客户像这样embedded您的代码不符合“ 按devise进行安全性”的原则。

从他们的angular度来看,您要求他们将预先捆绑的代码embedded到他们的网站中,将他们的网站暴露在代码中存在的任何隐藏的安全风险(无意或故意的恶意),这些风险将不受限制地访问他们网站的DOM,本地存储等等

这就是为什么使用iframe是在网站中embedded第三方内容的首选方法,因为该内容是从其主机站点的其余部分进行沙盒。

此外,按照“最低权限”的安全原则,他们(在您的指导下/示例)可以在iframe上设置sandbox属性,并通过白名单显式locking小组件的权限。

将小部件加载到iframe也会为您提供更多的与服务器通信的灵活性。 这现在可以是一个普通的meteor客户端,使用meteor的ddp与您的服务器通信。 你的其他build议也是可能的。

用户身份validation/标识取决于您的系统的详细信息。 这可以从使用meteor帐户 ,这会给你密码或社会authentication解决scheme。 或者你可以尝试匿名账户解决scheme,如artwells:accounts-guest 。

html5rocks关于沙盒内嵌框架的文章