Безопасность при использовании GWT RPC

У меня есть POJO в Google Web Toolkit как это, что я могу получить с сервера.

class Person implements Serializable {
  String name;
  Date creationDate;
}

Когда клиент вносит изменения, я сохраняю его назад к серверу с помощью GWT RemoteServiceServlet как это:

rpcService.saveObject(myPerson,...)

Проблема состоит в том, что пользователь не должен мочь измениться creationDate. Так как методом RPC является действительно просто POST HTTP к серверу, было бы возможно изменить creationDate путем изменения запроса POST.

Простое решение состояло бы в том, чтобы создать серию функций RPC как changeName(String newName), и т.д., но с классом со многими полями потребовал бы многих методов для каждого поля и будет неэффективен для изменения многих полей сразу.

Мне нравится простота наличия единственного POJO, который я могу использовать и на сервере и на клиенте GWT, но нуждаться в способе сделать это надежно. Какие-либо идеи?

Править

Я повторно отправляю с щедростью, чтобы попытаться видеть, существуют ли какие-либо другие идеи. Возможно, мой исходный вопрос сфокусировался слишком много на специфических особенностях GWT. Действительно я думаю, что это - универсальный вопрос для любой системы, которая использует JavaBeans для передачи данных между безопасным (контейнер сервлета) и небезопасный (веб-браузер) среда.

РЕДАКТИРОВАНИЕ 2

Кроме того, чтобы быть ясным, я использовал поле creationDate как пример проблемы. В действительности код, с которым я работаю, более сложен со многими различными полями.

5
задан user27478 25 May 2010 в 18:45
поделиться

7 ответов

Я рекомендую вам оставить единственный метод RPC и использовать POJO/bean mapper, например Dozer или Gilead.

  • С помощью Dozer вы создаете class-mapping, который используется для копирования свойств из одного объекта в другой. Если вы не укажете свойство в class-mapping, оно не будет скопировано.
  • В Gilead достаточно аннотации @ReadOnly transport.

Побочным преимуществом является то, что вам не нужно менять уровень доступа к данным (если он у вас есть). Не имеет значения, используете вы ORM или нет, с реляционной базой данных или нет.

3
ответ дан 13 December 2019 в 22:02
поделиться

Если клиент не может изменить дату создания и сохранить ее, измените сериализацию (например, оператор SQL UPDATE ), чтобы не сохранять это конкретное поле. Его следует устанавливать только с помощью INSERT (где он будет поступать либо с конечного сервера RPC, либо с сервера базы данных, если вы установите автоматическое значение по умолчанию).

3
ответ дан 13 December 2019 в 22:02
поделиться

Я бы использовал подход, основанный на разрешениях:

  • Назначьте роли пользователям (например, администратор, вошедший в систему пользователь, гость, ...) и
  • свяжите эти роли с разрешениями (например, может читать имя человека, может изменять имя человека - возможно, дополнительно ограничивая это определенными лицами и т. д.)

По каждому запросу от клиента выполнять проверку на сервере, если пользователю разрешено выполнять это действие. В случае с «датами создания» это, вероятно, никому не разрешено. Итак

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

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

Особый случай:

Если вам действительно нужно использовать дату создания, указанную клиентом, потому что вы хотите знать немного больше точно , когда пользователь щелкнул, единственное, что вы можете сделать, это чтобы убедиться, что указанная дата создания находится между предыдущим запросом и текущим запросом. Однако вам придется учитывать разницу в часах между сервером и клиентом. И вы не можете гарантировать точность.

1
ответ дан 13 December 2019 в 22:02
поделиться

Что ж ... академическим (то есть теоретически возможным, но совершенно непрактичным) решением может быть хеширование состояния объекта с использованием открытого ключа, закрытый ключ которого находится на сервере. Это может выглядеть примерно так:

  1. сервер генерирует пару открытого и закрытого ключей
  2. сервер отправляет открытый ключ вместе с реальными данными клиенту
  3. клиент вычисляет хэш полного состояния объекта вместе с открытый ключ
  4. клиент отправляет объект и хэш на сервер
  5. сервер пересчитывает хэш для подтверждения целостности пакета

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

Опять же, считайте это не более чем мысленным экспериментом ... Я бы не предлагал вам реализовать такой подход. В общем, вы должны быть в состоянии гарантировать, что логика на клиенте не была изменена, прежде чем вы перейдете к защите данных.

0
ответ дан 13 December 2019 в 22:02
поделиться

Почему бы не сделать поля закрытыми и предоставить только getCreationDate (), а не setCreationDate ()?

1
ответ дан 13 December 2019 в 22:02
поделиться

Вы можете просто игнорировать значения для неизменяемых полей.
Если это невозможно из-за того, как настроен механизм персистентности на сервере, то когда запрос попадает на сервер, получите другой экземпляр POJO из постоянного хранилища и заполните поля, которые являются неизменяемыми, теми, которые вы только что получили. Таким образом, если кто-то подделал некоторые поля, вам будет все равно.

Конечно, шифрование также может быть решением, чтобы помочь избежать несанкционированного вмешательства.

1
ответ дан 13 December 2019 в 22:02
поделиться

Разделите ваши объекты на две части. Одна содержит только поля, которые клиент может редактировать. Отправьте оба объекта клиенту, но сохраните только редактируемый объект, когда клиент вернет его. Здесь вы можете использовать наследование, чтобы упростить себе жизнь.

Если ваш инструмент отображения не гнется так, как вам нужно, реализуйте метод copy(), который копирует все поля из одного объекта в другой. Затем вы можете загрузить свежий экземпляр объекта из базы данных, скопировать в него редактируемые поля, а затем сохранить измененный объект.

1
ответ дан 13 December 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: