Безопасное связывание JPA в платформе Play - PullRequest
1 голос
/ 23 ноября 2011

У меня есть страница:

<input type="hidden" name="user.id" value="123" />
<input type="text" name="user.name" value="John" />

и действие:

public static void save(User user) {
    user.save();
}

Воспроизведение загружает сущность пользователя из базы данных с помощью параметра user.id, привязывает параметры HTTP к объектуи действие сохраняет его.

Это нормально для доверенного пользователя, такого как администратор, но ненадежный пользователь может изменить параметры HTTP на:

?user.id=456&user.name=John

и, таким образом, отредактировать другой объект.

Я проверяю, изменил ли пользователь user.id, также добавляя user.id в сеанс, а затем проверяю его равенство.Это прекрасно работает, так как сессия подписана и не может быть изменена, но как я могу легко проверить много объектов на странице - например, при массовом обновлении?Или просто сделать это широко распространенным по умолчанию?

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

Ответы [ 4 ]

0 голосов
/ 24 ноября 2011

Я попытаюсь прояснить свое решение, предложенное в конце моего вопроса, которое решит его в целом.

У каждого объекта будет другое поле - токен, который представляет собой идентификатор объекта, подписанный безопасным ключом.,Этот токен не должен храниться в базе данных, но может быть вычислен на лету.Когда отображается страница редактирования, она включает подписанный идентификатор, например, в поле __at:

<input type="hidden" name="user.id" value="123" />
<input type="hidden" name="user.__at" value="9e01f3c8...4ccba38b9" />
<input type="hidden" name="user.address.id" value="124" />
<input type="hidden" name="user.address.__at" value="83df099...4a276fc8" />

Когда эти объекты связываются в контроллере, он снова поет полученный идентификатор и сравнивает его с полем __at,Если эти подписанные значения не совпадают, это означает, что пользователь изменил идентификатор.

Я не эксперт по шифрованию и не смотрел, как подписывается сеанс Play, но я думаю, что это похоже.Как вы думаете, этот механизм может работать?

0 голосов
/ 23 ноября 2011

Вы должны убедиться, что сохранение может быть вызвано только авторизованными пользователями.Игра в один конец!позволяет сделать это с помощью аннотации @Before.Пример из документации по воспроизведению:

@Before(unless={"login", "authenticate"})
static void checkAuthenticated() {
    if(!session.contains("user")) {
        login();
    }
}

Атрибут сеанса user будет помещен в сеанс только после аутентификации пользователя.Только аутентифицированные пользователи смогут отправлять HTTP-запросы на ваш маршрут save().Обратите особое внимание на параметры аннотаций unless и only.

Приведенный выше код взят из примера OpenID в Play!документация.Я использовал это один раз, и до сих пор, кажется, это работает отлично.

0 голосов
/ 23 ноября 2011

Из того, что я понимаю, вы хотите, чтобы аутентификация и авторизация.

Аутентификация говорит вам, кто пользователь, и вы можете pHk ответить, чтобы сделать это, или использовать безопасный модуль

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

Он основан на безопасном модуле, но правила на основе drools дают вам всю необходимую гибкость.

0 голосов
/ 23 ноября 2011

Вы можете использовать метод checkAuthenticity в контроллере для проверки подлинности отправленной формы.

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

...