Meteor 安全指南

介绍

安全的宗旨

  1. 只有在服务器端的代码才值得信任
  2. 其他所有: 客户端代码,Method 和 publication 的参数都不能被信任

所以,大部分的工作都是这两部分

  1. 在服务器端对所有来自客户端的输入 (Meteor.call, Meteor.subscribe) 进行验证
  2. 不要泄露任何秘密信息到客户端。前后端代码分开

避免使用 allow、deny

不要使用 allow、deny,就是不要允许在客户端修改 MongoDB 数据库。推荐使用 Method 在服务器端更新数据库。可以使用一下代码来禁止客户端更新数据库。

Lists.deny({  
  insert() { return true; },
  update() { return true; },
  remove() { return true; },
});

Methods

验证参数

如果不验证参数,有人传入 {} 的话,下面代码会删除整个 collection

Meteor.methods({  
  removeWidget(id) {
    if (! this.userId) {
      throw new Meteor.Error('removeWidget.unauthorized');
    }

    Widgets.remove(id);
  }
});

可以使用 mdg:validated-method 这个包做验证。

userId

在 Method 里只使用 this.userId 来获取信息。只有在把其他用户作为目标,例如发送消息时才使用从客户端传来的 userId。或者管理员修改其他用户信息时。

限制 Method 调用频率。

为了防止恶意暴力破解,可以使用 DDPRateLimiter.addRule 来限制 Method 的调用频率。可以限制到每个链接每秒钟可以调用的次数。

Publications

  1. 使用 Check 包 或者 schema 来验证参数。
  2. 不要使用 userId 作为参数
  3. 不要使用通用参数
  4. 限制调用频率

限制 fields

避免不必要的信息泄露到客户端。

Publication reactivity

在登录用户更改后,在 Publication 里只有 Collection.find 会再次运行,所以之前的代码不会运行,这就要求在 find 里要验证例如数据的所有权。

Server 代码

if (Meteor.isServer) 会发送到客户端,所以最好不要使用。

检查清单:

  1. 去除默认的 insecure、autopublish 包
  2. 使用 audit-argument-checks 确保验证所有 Method 和 publication 的参数
  3. Deny 写 user doc 的 profile field
  4. 使用 Methods 取代客户端数据库更新
  5. 过滤 publication 的 fields,避免不必要的信息发布到客户端
  6. 避免在 Blaze 里使用 raw HTML
  7. 不要在代码里直接使用 secret API keys 和密码等敏感信息
  8. 重要的是数据而不是 UI,重定向 UI 不能解决安全问题
  9. 在服务器端使用 this.userId 确认登录用户
    10.使用 browser policy