Meteor позволяет очень легко начать и возиться. Но у такого подхода «запуск и запуск за секунды» есть и обратная сторона.
Давайте посмотрим на файл packages-File, который будет создан, если мы начнем новый проект Meteor:

cd my_new_meteor_project<br />
cat .meteor/packages<br />

Мы увидим, что по умолчанию установлены три разных пакета:

  • метеоритная платформа
  • автопубликовать
  • ненадежный

Пакет meteor-platform-Package гарантирует, что минимальная функциональность для запуска и игры с Meteor будет у вас под рукой.

Но есть также пакеты autopublish- и insecure.

Автопубликация гарантирует, что все данные вашей базы данных (каждый документ) всегда будут автоматически опубликованы для всех ваших клиентов.

Insecure позволяет писать команды MongoDB (например, Posts.insert({ title: 'test' })), которые будут выполняться на клиенте (а также могут быть введены в консоль разработки) и затем распространяются на сервер. без каких-либо проверок разрешений.

Эти два пакета предназначены для облегчения разработки.
Но вам определенно следует удалить эти два пакета, если вы хотите опубликовать свое приложение Meteor для широкой публики.

Просто запустите эту команду, чтобы удалить эти два пакета из вашего проекта:

meteor remove autopublish insecure<br />

Кроме того, я бы порекомендовал удалять пакеты в начале каждого нового приложения Meteor (если вы действительно не собираетесь использовать предоставленную функциональность позже), чтобы у вас не было никаких дополнительных изменений кода после их удаления.

Перепубликация данных

Давайте взглянем на типичный код публикации:

Meteor.publish('posts', function() {<br />
  return Posts.find();<br />
});<br />

Здесь мы публикуем все наши посты в клиенте.
Что в этом плохого? Плохо то, что вы публикуете весь документ. Это оказывает негативное влияние на поведение загрузки вашего приложения, но также может привести к утечке информации, связанной с документом, которая не должна публиковаться (например, число отчетов, которое содержит значение того, как часто об этом сообщении сообщали другие пользователи).

Вы всегда должны публиковать только необходимые данные для клиентов. Вы можете сделать это с помощью поля-оператора:

Meteor.publish('posts', function() {<br />
  return Posts.find({}, {<br />
    fields: {<br />
      title: true,<br />
      body: true<br />
    }<br />
  });<br />
});<br />

Таким образом публикуются только заголовок и тело (и _id, который будет опубликован по умолчанию). Все остальное остается в базе данных сервера. Уменьшенный размер данных также положительно влияет на время загрузки ваших приложений.

Методы против обработки данных на стороне клиента

Существует два основных способа манипулирования данными базы данных в Meteor.
Первый — это манипулирование данными на клиенте с прямыми вызовами MongoDB к базе данных Minimongo, которая запускается прямо в браузере пользователя. Затем эти изменения отражаются в базе данных на стороне сервера.

Другой возможностью является использование Meteor-Methods. Вы определяете метод (который может работать в обеих средах) и вызываете метод на стороне клиента.

Когда вы используете способ обработки данных на стороне клиента, вы пишете команды MongoDB, которые выполняются напрямую. После того, как вы удалили небезопасный пакет, вы должны написать правила разрешения и запрета, чтобы только разрешенные пользователи могли изменять данные.
Вот тут-то и начинаются проблемы.
Очень сложно написать правильные разрешающие и запрещающие правила.

Сообщество Meteor недавно запустило вызов, в котором пользователи должны сформулировать разрешающие и запрещающие правила для операции обновления.
Вы должны попытаться решить эту задачу самостоятельно. Результаты этого вызова обрисовывают здесь очень важный вывод.

Чертовски сложно сделать это правильно.

Просто держитесь подальше от манипулирования данными на стороне клиента, если вы не уверены, что ваши разрешающие и запрещающие правила являются пуленепробиваемыми.

Если вам действительно нужен более простой контроль над манипулированием данными, вам следует использовать метод Meteor и вызывать этот метод из клиента. Таким образом, ваши проверки безопасности будут менее запутанными и их будет проще реализовать.

Чек-Пакет

Одним из недооцененных пакетов, который вам обязательно следует использовать, является check-Page, поддерживаемый группой разработчиков Meteor.

Помните те времена, когда вы имели дело с SQL-инъекциями?
Есть нечто подобное и с такими базами данных, как MongoDB. И ваше приложение Meteor по умолчанию уязвимо.

Распространенное высказывание, которому вы должны следовать, звучит так: «Никогда не доверяйте пользовательскому вводу». Check-Package упрощает проверку пользовательского ввода до его обработки и гарантирует, что введенный пользователем ввод соответствует ожидаемому типу (например, мы ожидаем строку или целое число). Метеор выдаст исключение, если входные данные не соответствуют шаблону.

Чтобы использовать check-Package, просто добавьте его в свой проект Meteor с помощью следующей команды:

meteor add check<br />

После этого вы можете просто проверить параметры, как показано в следующем примере кода:

// Using check in a publication<br />
Meteor.publish("post", function (_id) {<br />
  check(_id, String);<br />
  return Posts.find({_id: _id});<br />
});</p>
<p>// Using check in a method<br />
Meteor.methods({addPost: function (_id, title, body) {<br />
  check(_id, String);<br />
  check(title, String);<br />
  check(body, String);<br />
  // ...<br />
}});<br />

Всегда проверяйте точки входа для пользовательских данных с помощью чек-пакета!

Пакет Audit-argument-checks

Итак, недавно мы говорили о check-Package. Но как узнать, если вы везде проверили все параметры?

Вот тут и приходит на помощь пакет audit-argument-checks-Package. Он гарантирует, что вы правильно проверите все свои параметры. Если вы пропустили параметр, проверьте, например, метода, возникает исключение, и Meteor запрещает выполнение этого метода до тех пор, пока вы не добавите соответствующий параметр Check.

Все это работает автоматически после того, как вы просто добавили пакет с помощью следующей команды:

meteor add audit-argument-checks<br />

Пакет политики браузера

Это еще один отличный пакет, который делает ваше приложение более безопасным.
Он реализует предложение подхода браузерной политики.

Пакет предоставляет вам набор инструментов для управления поведением браузера пользователей, когда, например. должны быть загружены внешние ресурсы или приложение может быть помещено в iFramed на другой веб-сайт.

Выполните следующую команду, чтобы добавить пакет:

meteor add browser-policy<br />

После этого вам станут доступны различные функции.

Вот пример, который определяет, какие внешние ресурсы разрешено загружать в ваше приложение Meteor:

// This file lives on the server-Side<br />
BrowserPolicy.content.allowOriginForAll('http://ajax.googleapis.com');<br />
BrowserPolicy.content.allowOriginForAll('https://ajax.googleapis.com');<br />
BrowserPolicy.content.allowOriginForAll('http://*.youtube.com');<br />
BrowserPolicy.content.allowOriginForAll('https://*.youtube.com');<br />
BrowserPolicy.content.allowOriginForAll('http://*.amazonaws.com');<br />
BrowserPolicy.content.allowOriginForAll('https://*.amazonaws.com');<br />

Разрешена загрузка только скриптов Google, YouTube и Amazon AWS. Все остальное заблокировано.

Следуйте документации пакета, чтобы узнать, что еще предоставляет этот пакет.

Поле профиля Meteor.user()

Знаете ли вы, что поле профиля Meteor.user(), которое автоматически предоставляется пакетом учетных записей Meteor, редактируется клиентом и автоматически публикуется?

В этом поле удобно хранить информацию о пользователе, такую ​​как пол или имя и фамилию. Но не более того. Не храните здесь конфиденциальную информацию.

Недавно было предложено объявить поле устаревшим, потому что его поведение часто недооценивают и неправильно понимают.

Правильное использование Meteor.userId()

Допустим, вы хотите опубликовать что-то, что должен видеть только пользователь, вошедший в систему в данный момент.
Мы притворяемся, что у нас есть платформа для ведения блогов, на которой разные компании и их пользователи публикуют информацию о стратегии своих компаний.
Пользователь, вошедший в систему в данный момент. написал черновик сообщения, которое еще не опубликовано, поскольку оно содержит конфиденциальную информацию о призыве компании к получению дохода.

Если мы хотим показать вошедшему в систему пользователю все его сообщения (включая его черновики), мы можем сделать что-то вроде этого:

Meteor.publish('posts', function(userId) {<br />
  check(userId, String);<br />
  return Posts.find({<br />
    userId: userId<br />
  });<br />
});<br />

— Что в этом плохого? ты можешь подумать.

Эту публикацию можно легко использовать для демонстрации сообщений других пользователей.
Просто откройте консоль разработчика в своем браузере и подпишитесь на публикацию с другим идентификатором пользователя.

Лучший способ справиться с такой ситуацией — положиться на userId-Helper, который предоставляется пакетом учетных записей Meteor:

Meteor.publish('posts', function() {<br />
  return Posts.find({<br />
    userId: this.userId<br />
  });<br />
});<br />

Таким образом, автоматически используется идентификатор пользователя, выполнившего вход в систему, и вы находитесь на стороне сохранения.

Заключение / Дополнительные ресурсы

Я надеюсь, что эта запись в блоге была для вас полезной.
Безопасность — очень важная тема при разработке приложений.
Эта запись в блоге — только отправная точка. Есть и другие замечательные сообщения в блогах, которые вам действительно стоит проверить: