У меня есть 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
как пример проблемы. В действительности код, с которым я работаю, более сложен со многими различными полями.
Я рекомендую вам оставить единственный метод RPC и использовать POJO/bean mapper, например Dozer или Gilead.
Побочным преимуществом является то, что вам не нужно менять уровень доступа к данным (если он у вас есть). Не имеет значения, используете вы ORM или нет, с реляционной базой данных или нет.
Если клиент не может изменить дату создания и сохранить ее, измените сериализацию (например, оператор SQL UPDATE
), чтобы не сохранять это конкретное поле. Его следует устанавливать только с помощью INSERT
(где он будет поступать либо с конечного сервера RPC, либо с сервера базы данных, если вы установите автоматическое значение по умолчанию).
Я бы использовал подход, основанный на разрешениях:
По каждому запросу от клиента выполнять проверку на сервере, если пользователю разрешено выполнять это действие. В случае с «датами создания» это, вероятно, никому не разрешено. Итак
Клиент обычно указывает человека с помощью какого-либо идентификатора (может быть пустым для вновь созданного человека), который сервер может использовать для поиска существующих лиц. Подделка идентификатора не имеет значения, потому что пользователь в любом случае может изменять только данные, указанные в его разрешениях.
Особый случай:
Если вам действительно нужно использовать дату создания, указанную клиентом, потому что вы хотите знать немного больше точно , когда пользователь щелкнул, единственное, что вы можете сделать, это чтобы убедиться, что указанная дата создания находится между предыдущим запросом и текущим запросом. Однако вам придется учитывать разницу в часах между сервером и клиентом. И вы не можете гарантировать точность.
Что ж ... академическим (то есть теоретически возможным, но совершенно непрактичным) решением может быть хеширование состояния объекта с использованием открытого ключа, закрытый ключ которого находится на сервере. Это может выглядеть примерно так:
Предполагая, что пара ключей изменяется при каждом запросе и что пользователь может не вмешиваться в процесс хеширования (что он может, но может быть достаточно сложным, чтобы сделать его полезным в некоторых случаях использования), сервер сможет обнаруживать любые изменения в состоянии объектов, сделанные после того, как хэш был вычислен на клиенте. .
Опять же, считайте это не более чем мысленным экспериментом ... Я бы не предлагал вам реализовать такой подход. В общем, вы должны быть в состоянии гарантировать, что логика на клиенте не была изменена, прежде чем вы перейдете к защите данных.
Почему бы не сделать поля закрытыми и предоставить только getCreationDate (), а не setCreationDate ()?
Вы можете просто игнорировать значения для неизменяемых полей.
Если это невозможно из-за того, как настроен механизм персистентности на сервере, то когда запрос попадает на сервер, получите другой экземпляр POJO из постоянного хранилища и заполните поля, которые являются неизменяемыми, теми, которые вы только что получили. Таким образом, если кто-то подделал некоторые поля, вам будет все равно.
Конечно, шифрование также может быть решением, чтобы помочь избежать несанкционированного вмешательства.
Разделите ваши объекты на две части. Одна содержит только поля, которые клиент может редактировать. Отправьте оба объекта клиенту, но сохраните только редактируемый объект, когда клиент вернет его. Здесь вы можете использовать наследование, чтобы упростить себе жизнь.
Если ваш инструмент отображения не гнется так, как вам нужно, реализуйте метод copy()
, который копирует все поля из одного объекта в другой. Затем вы можете загрузить свежий экземпляр объекта из базы данных, скопировать в него редактируемые поля, а затем сохранить измененный объект.