2010-05-21 2 views
5

У меня есть POJO в Google Web Toolkit, который я могу получить с сервера.Безопасность при использовании GWT RPC

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

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

rpcService.saveObject(myPerson,...) 

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

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

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

EDIT

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

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

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

+0

О EDIT 2: Я не думаю, что существует большая разница между полем createDate и другими полями, за исключением того, что у creatDate могут быть несколько дополнительных сложностей, характерных для обработки даты и времени. Разрешения - это обычный способ обработки всех входящих и выходящих данных - для некоторых объектов/полей это очень просто, всегда отрицая все обновления. Для других объектов/полей разрешения могут быть очень сложными, основываясь на проверках сложных структур данных, оцениваемых индивидуально для каждого пользователя. В любом случае проверки выполняются на сервере - не делайте их на клиенте. –

ответ

3

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

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

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

0

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

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

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

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

+1

Почему кто-то добавляет сложность криптографии, чтобы избежать обновлений базы данных в заранее определенных столбцах? – jweyrich

+0

Как я уже сказал, это не то, что я бы рекомендовал делать. Я понял, что вопрос в основном заключается в том, «как следует помешать пользователю изменять часть значения (в данной технологической среде)». Очевидным решением для меня является подписание данных, чтобы гарантировать, что он не был подделан. Может быть, мы поняли этот вопрос по-разному. –

+0

Вы понимаете проблему как «Как избежать манипуляций с трафиком». Если бы это было так, он мог бы просто использовать HTTPS. – jweyrich

3

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

+2

Точно. «Никогда не доверяйте клиенту». Если у вас есть информация, которую пользователь не может изменить, не доверяйте данным, поступающим от клиента. Если вы не сохраняете данные в постоянном хранилище до тех пор, пока пользователь не сможет его изменить, предварительно выполните его сериализацию и сохраните временную копию, чтобы вытащить данные, которые не должны были быть изменены. –

1

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

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

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

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

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

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

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

+0

Этот ответ касается главным образом общей части в конце вашего вопроса. С GWTRPC - если вы хотите отправить весь объект Person - вы можете разрешить ему содержать дату создания, но либо a) игнорировать его, либо b) проверить, совпадает ли он с тем, что на сервере. –

1

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

1

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

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

1

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

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

Смежные вопросы