Безопасность при использовании GWT RPC - PullRequest
5 голосов
/ 21 мая 2010

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

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

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

rpcService.saveObject(myPerson,...)

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

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

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

EDIT

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

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

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

Ответы [ 7 ]

3 голосов
/ 22 мая 2010

Я рекомендую вам придерживаться одного метода RPC и использовать POJO / маппер бобов, например Dozer или Gilead .

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

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

3 голосов
/ 21 мая 2010

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

1 голос
/ 31 мая 2010

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

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

1 голос
/ 31 мая 2010

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

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

1 голос
/ 29 мая 2010

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

1 голос
/ 25 мая 2010

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

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

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

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

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

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

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

0 голосов
/ 21 мая 2010

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

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

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

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

...