将数据传递给客户端JavaScript(最好不带视图引擎或cookie)

时间:2017-07-07 17:34:17

标签: javascript node.js express

第一部分:问题介绍

简短的说明:我需要将数据从服务器传递到客户端,但这些数据不需要显示在客户端。相反,客户端套接字使用数据来加入正确的房间。转到第二部分:解决方案尝试

长篇故事:

对于我的第一个Web开发项目,我正在尝试创建一个远程演示者(即使用移动设备来控制桌面上的Google幻灯片演示文稿)。

在前端,我一直在使用普通的旧HTMl,CSS和vanilla JS,而后端则涉及NodeJS,Express框架和Socket.io。

以下是用户流程的简要概述:当用户通过桌面上的Google登录进行身份验证时,网站将打开一个套接字连接,该连接会自动加入由套接字ID标识的房间。在用户登录桌面端之后,用户将(现在)将此套接字ID视为可用于在移动端登录的“密钥”。

因此,我有server.js处理路由和表单操作(即在移动端提交的密钥),如下所示:

// Store all the currently connected web clients
var webClients = [];

// Index route -- home page for website and mobile site
app.get('/', function (req, res) {
  // Basic user agent check - test for mobiles
  var userAgent = req.headers['user-agent'];
  if (/mobile/i.test(userAgent)) {
      // Send mobile to the mobile login site
      res.sendFile(__dirname + '/pages/mobile.html');
  } else {
      // Send desktop to the main site
      res.sendFile(__dirname + '/pages/index.html');
  }
});

// Dealing with secret key input
app.post('/secretKey', function(req, res) {

    // Store the secret key in a variable first
    var secretKey = req.body.secretKey;

    // Check if the secret key matches with any key in the database (current session)
    var index = webClients.indexOf(secretKey);

    // Send the user to the mobile controls if there is something that matches
    if (index != -1) {
        res.sendFile(__dirname + '/pages/mobileControl.html');
    } else {
        res.redirect('/');
    }
  }

});

不幸的是,我遇到了麻烦。加载移动控件页面后,将在移动端打开另一个套接字实例。为了确保移动设备正在控制正确的演示文稿,我需要让移动端的套接字加入与桌面套接字相同的房间(即具有桌面套接字ID的房间)。因此,我需要将桌面套接字ID传递到移动端,以便移动套接字可以连接到正确的房间。

第二部分:解决方案尝试

我知道其他几位用户已经在SO上提出了类似的问题。例如:

通过这些,我可以总结一些重要的建议:

  1. 使用Jade,ejs等模板系统
  2. 我查看了Jade和ejs,我不愿意使用这些模板系统,因为我怀疑它们对于我在这里尝试实现的内容可能有点过分 - 只需将字符串从服务器传递到客户端JavaScript而不渲染视图中的字符串。此外,我并不真正需要这些模板系统提供的部分内容,进一步强化了我的信念,即这些可能是过度的。

    1. 将数据存储在Cookie中,并在客户端JavaScript上访问Cookie
    2. 目前,这个解决方案对我来说最吸引人,因为它似乎是最简单的方法。我可以简单地做一些事情:

      var options = {
           headers: {
                'set-cookie' : roomId=secretKey
           }
        };
      res.sendFile(__dirname + '/pages/mobileControl.html', options);
      

      然后,我可以通过mobileControl.js之类的操作访问document.cookie内的Cookie中的数据。但是,我已经读过这种方法存在安全问题,例如跨站点脚本(XSS)攻击。因此,我也不愿意使用这种方法。

      1. 将数据发送到另一条路线,并在渲染html后使用XMLHttpRequest检索数据
      2. 除了这三种方法之外,我还研究了实现用户会话,但我认为这不是我的解决方案,因为用户会话可能会在稍后阶段进入以允许登录持续存在。

        那么,您认为在这种情况下我应该使用哪种方法?我应该跟2一起调整,并调整cookie的HttpOnly字段吗?还有其他建议吗?非常感谢!

1 个答案:

答案 0 :(得分:2)

如果你不想使用一个完整的模板引擎(尽管我认为这不会超过这个 - 这就是模板引擎的用途),那么只需要替换一个字符串呢?

添加类似

的内容
<script>var SECRET_KEY = '{{{SECRET_KEY}}}';</script>

在HTML文件中,流式传输文件而不是发送文件,并使用stream-replace之类的内容将{{{SECRET_KEY}}}字符串替换为您的密钥。

未经测试的例子:

var fs = require('fs');
var replace = require('stream-replace');

app.post('/secretKey', function(req, res) {

    // Store the secret key in a variable first
    var secretKey = req.body.secretKey;

    // Check if the secret key matches with any key in the database (current session)
    var index = webClients.indexOf(secretKey);

    // Send the user to the mobile controls if there is something that matches
    if (index != -1) {
        fs.createReadStream(__dirname + '/pages/mobileControl.html')
            .pipe(replace('{{{SECRET_KEY}}}', secretKey))
            .pipe(res);
    } else {
        res.redirect('/');
    }
});

然后,您就可以在脚本中使用SECRET_KEY变量。