Как представить контроль доступа на уровне атрибутов RESTful?

Я ломал себе голову и гуглил целую вечность, так и не придумав удовлетворительного способа справиться с этим. Я хочу написать красивую полностью RESTful-службу для возврата ресурсов, но данные, которые у вас есть, на чтение (или запись) самых разных ресурсов в зависимости от вашей роли. Так, например, пользователь может видеть свой личный номер телефона в своем профиле, как и администратор сайта, но не другой пользователь. Анонимный посетитель может не видеть настоящее имя другого пользователя, но другие пользователи (и администратор сайта) могут. Существует около 4 или 5 уровней доступа и правил, определяющих, какие атрибуты могут быть прочитаны или записаны. Я доволен написанием, поскольку клиент может ПОСТАВИТЬ изменения, а сервер не обязан принимать их все (или вообще), но чтение - это моя проблема.

<user>
 <id>jimbob</id>
 <real-name>Jim Roberts</real-name> <!-- only logged-in users should see this -->
 <phone-number>+1 42424151</phone-number> <!-- only the user and admin users should see this -->
</user>

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

<user>
 <id>...</id>
 <link rel="more" href="extra-user-profile-data-for-logged-in-users"/>
 <link rel="more" href="extra-user-profile-data-for-senior-users"/>
 <link rel="more" href="extra-user-profile-data-for-admin-users"/>
 <link rel="more" href="extra-user-profile-data-for-superadmin-users"/>
</user>

Обратите внимание - я не борюсь ни с одним из

  • Аутентификация
  • Контроль доступа на уровне ресурсов
  • Реализация контроля доступа или авторизации на стороне сервера

Я борюсь с

  • Как представить ресурсы, которые на «нормальном» HTML-сайте будут разными для разных людей, в истинно RESTful-стиле.

Это похоже на действительно распространенную проблему, которая должна быть у всех, но я ничего не могу найти по ней! Пожалуйста помоги!


person Gareth Boden    schedule 22.12.2011    source источник
comment
Я считаю целесообразным опустить элементы XML, которые соответствуют свойствам, которые пользователь не имеет права видеть. Я думаю, это согласуется с тем, сколько ролевых веб-приложений представляют данные в HTML-формах.   -  person EJK    schedule 23.12.2011
comment
Это делает его некэшируемым, поскольку в противном случае общедоступные данные были бы смешаны с некоторым (неизвестным) подмножеством ограниченных данных в том же (кешированном) представлении.   -  person Gareth Boden    schedule 04.01.2012
comment
для меня звучит как простая проблема. 1. пользователь аутентифицируется. 2. пользователь запрашивает URI 3. реализованный вами механизм контроля доступа срабатывает и перехватывает запрос URI. 4. Монитор ресурсов создает шаблон данных, которые будут возвращены запрашивающему пользователю. этот шаблон действует как своего рода билет. 5. Служба выполняет запрос пользователя, указанный в URI, на основе шаблона, полученного от монитора ресурсов. 6. Сервис возвращает результат пользователю. хмммм   -  person ultrajohn    schedule 19.01.2015


Ответы (1)


Если подумать, User ресурс, который видит клиент-администратор (со всеми видимыми полями), является точно таким же ресурсом, который видит анонимный или менее привилегированный клиент. URI идентичен, но представление, которое они видят, отличается.

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

Таким образом, администратор может получать контент с типом мультимедиа application/vnd.yourcompany.user.full+xml как тело, возвращаемое GET на вашем User ресурсе, и оно будет содержать все возможные поля.

Однако анонимный пользователь может получить полезную нагрузку в кодировке, скажем, application/vnd.yourcompany.user.limited+xml, которую ваша документация будет четко описывать как представление, которое может содержать или не содержать все элементы из версии full. Клиент должен был бы использовать гибкий декодер или схему, которая допускала бы полное отсутствие определенных элементов.

В качестве альтернативы вы можете вернуть всю информацию о ресурсе, но использовать специальное значение поля, чтобы указать, что конкретное значение было отредактировано:

<user>
 <id>jimbob</id>
 <real-name>--FORBIDDEN--</real-name> 
</user>

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

Окончательное решение, которое необходимо принять, заключается в том, возвращать ли ссылки на другие ресурсы, по которым нельзя будет перемещаться в зависимости от учетных данных, предоставленных клиентом. На мой взгляд, эти ссылки должны всегда возвращаться, даже если эти учетные данные не будут работать. Почему? Потому что клиент теоретически может предоставить другие учетные данные при вызове этих URI. Даже если они этого не сделают, результирующая 401 задача может привести к тому, что клиент в конечном итоге предоставит их. Но если они даже не получат URI, они никогда не смогут принять это решение.

person Brian Kelly    schedule 23.12.2011
comment
Привет, спасибо за подробный и продуманный ответ. Проблема с «ограниченным» типом мультимедиа заключается в том, что контент все равно будет варьироваться в зависимости от роли и, следовательно, не будет кэшироваться. Поскольку то же самое применимо почти ко всем ресурсам в моей системе, это сильно снизит производительность. Вы правы в том, что мы не хотим связывать роли с типами медиа. Мне нравится идея свести проблему к альтернативным представлениям, это имеет смысл, но, к сожалению, я пока не вижу практического решения. Может ли быть какой-то заголовок в ответе (но не авторизация), на который ссылается заголовок Vary для кеширования? - person Gareth Boden; 04.01.2012
comment
В идеале я хотел бы убедиться, что все, что обслуживается, имело публично кешируемое представление для общедоступных данных и частное кешируемое представление (я) для данных, зависящих от роли, чтобы снова попасть в систему для того же ресурса из того же источника получает все из кеша. - person Gareth Boden; 04.01.2012