与Web Widget-Meteror,React,Node进行通信



我正在构建一个聊天仪表板和小部件,客户应该能够将小部件放入他们的页面中。一些类似的例子是对讲或漂移。

当前,"主要"应用程序写在seeor.js中(它的前端在React中)。我已经编写了<Widget />组件,并将其扔进了/widget目录中。在此目录中,我还有一个index.jsx文件,该文件仅包含以下内容:

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

i然后在index.jsx上设置了带有入口点的WebPack配置,并且在运行WebPack时,请在公共目录中吐出bundle.js

然后可以通过简单地包括scriptdiv

将其包含在另一页上。
<script src="http://localhost:3000/bundle.js" type="text/javascript"></script>
<div id="widget-target"></div>

一些问题:

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

1此实现是什么问题?他们是否有任何安全问题?前面链接的两个示例似乎都以一种或另一种形式使用iframe。

正如@jeremyk所述,您在iframe中更安全。话虽如此,许多第三方(Facebook,Ga,...)都有一条中间路线,包括对讲:

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

例如,Intercom要求客户在其页面上包含一些脚本:https://developers.intercom.com/docs/single-page-app#section-step-section-step-1-include-intercom-js-library,这很小(https://js.intercomcdn.com/shim.d97a38b5.js)。这加载了设置iframe并公开其API的额外代码

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

有三个选项:

  • 将您的小部件构建为整个流星应用程序。这将增加需要加载的代码的大小。为了换取额外的代码,您可以通过流星API与后端进行通信,例如Meteor.Call,获取所有数据的反应性(例如,如果您通过主要的Meteor应用程序向用户发送响应,则响应将弹出只要在同一数据库上(不需要在同一服务器上)和乐观的UI,就无需做任何工作即可完成工作。简而言之
  • 不要包括流星。由于您正在构建聊天应用程序,因此可能需要socket.io,而不是传统的REST API。可以肯定的是,您可以混合在一起
  • 使用流星DDP。(这有点像socket.io,但是对于流星。流星应用程序用于服务器的所有请求)这将包含较少的东西,而与REST API/socket.io相比,完整的流星可能更容易集成到流星后端并且将是整个流星的额外工作。

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

本部分可能应该在客户网站上(iframe中的VS)进行一些工作,以便您可以在其页面上设置cookie,并将该数据发送到您的iFrame,该数据将与您的服务器交谈并识别用户。当您使用artwells:accounts-guest(基于meteor:accounts-base)是否取决于您决定将流星包含在iframe中。

如果您的iframe中没有流星,则可以做类似:

的事情。
  • 通过简单地在服务器上进行操作用户创建

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

要求您的客户这样的嵌入代码不遵循设计的安全原则。

从他们的角度来看,您要求他们将您的预借入的代码嵌入其网站,将其网站暴露于您的代码中存在的任何隐藏的安全风险(无意中或故意恶意),这些风险将无限制地访问其网站的网站。dom,localstorage等

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

此外,遵循"最小特权"的安全原则(在您的指导/示例中)可以在iframe上设置 sandbox属性,并通过白名单明确地封锁了窗口窗口的特权。

将小部件加载到iframe中还将为您提供更大的灵活性,以与服务器进行通信。现在,这可能是普通的流星客户,使用流星的DDP与服务器进行通信。您的其他建议也是可能的。

用户验证/标识取决于系统的详细信息。这可能从使用流星帐户来为您提供密码或社交验证解决方案的范围。或者,您可以尝试使用匿名帐户解决方案,例如Artwells:Account councor-guest。

html5rocks关于沙盒iframes

的文章

最新更新