Каков предпочтительный способ создания шаблонов в элементе intercept-url
в Spring безопасности?
Я создаю веб-службу (RESTful), и в настоящее время я требую, чтобы все пользователи вошли в систему и имели роль ROLE_USER
. Затем дополнительные ограничения выполняются аннотациями @PreAuthorize
на уровне службы. Однако общепринято также добавлять несколько элементов intercept-url
, которые имеют разную конфигурацию?
Использование intercept-url в Spring безопасности
Ответ 1
Я должен думать, что "предпочтительный путь" [обязательно] субъективен. У меня были <intercept-url>
элементы в security.xml
, но они оставили их в пользу аннотаций @RequestMapping
с @PreAuthorize
на контроллерах. Это чисто личное предпочтение (в моем случае), поскольку я предпочитаю хранить вещи в Java, а не в пространствах имен XML, насколько это возможно.
Вы можете использовать один, другой или оба, и вы можете сделать аннотацию для улучшения XML - вы можете, например, иметь что-то вроде следующего:
security.xml
<intercept-url pattern="/something" access="hasRole('ROLE_USER')"/>
YourController.java
@RequestMapping(value="/something/else")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getSomethingElseContents(){ return "somethingelse"; }
Как я уже сказал, кажется, что это просто вопрос предпочтения. Преимущество использования пространства имен XML заключается в том, что правила базового доступа находятся в одном месте, легко читаются и легко отслеживаются. Правила, налагаемые @PreAuthorize
(или другими вариантами аннотации), особенно сексуальны, потому что вы можете называть свое собственное выражение SpEL в них и основывать свое разрешение на доступе к переданным параметрам или полям, доступным классу (т.е. @PreAuthorize("@my.project.package.hasMagicPower(#power.INVISIBILITY)")
), или их комбинаций. Вы можете применять логические и динамические разрешения, которые в противном случае недоступны для параметра пространства имен.
Конечно, вы можете применять рудиментарную логику с помощью "и", "или" и "!". Связи в выражениях SpEL в пространстве имен (и вы можете получить доступ к внешним классам [логическим] методам с помощью указателя @
в XML), но все, указанное в XML, должно быть статическим.
tl; dr: предпочтение отдается личным предпочтениям, но если вам нужна или нужна динамическая гибкость в обработке разрешений, вы должны использовать аннотации. Если вы не хотите и не нуждаетесь в динамической гибкости, у вас есть опция (и звуковой аргумент подсказывает, что опция пространства имен лучше по отношению к SoC). Я предпочитаю, чтобы Java обрабатывал его для гибкости, и поскольку, как только я настроил свой XML, я хочу оставить его в покое и сосредоточиться на Java. Кроме того, существует несколько убедительный контраргумент представления SoC, который заключается в том, что правильно написанное Java-приложение будет иметь свои контроллеры в легкодоступных пакетах с явным контролем по имени.
еще tl; dr: Мех. Шесть из них, полдюжины других. Я говорю po-tay-to.
Ответ 2
Большинство веб-приложений, использующих Spring Безопасность, имеют только пару intercept-url
, потому что у них есть только самые основные требования безопасности. Вам необходимо иметь неавторизованный доступ к экранам входа и входа в систему и, как правило, к некоторым аспектам публичного сайта, так что это может быть несколько шаблонов URL. Тогда часто есть раздел администратора, а затем все остальное ROLE_USER
.
Если вам нужно больше ролей, обычно их связывать с компонентами пути URL верхнего уровня. Хотя это и не требуется, это облегчает уверенность в том, что ресурсы надлежащим образом защищены.
<http realm="Contacts Realm" use-expressions="false">
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/admin/*" access="ROLE_ADMIN"/>
<intercept-url pattern="/secret/*" access="ROLE_SECRET"/>
<intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN,ROLE_SECRET"/>
<http-basic/>
</http>
Вы должны решить, на основе ваших случаев использования, хотите ли вы, чтобы люди имели несколько ролей. Это немного сложнее в управлении, поэтому большинство людей с простой безопасностью настроили его так, чтобы пользователи имели ровно одну роль, а затем разрешили нескольким ролям доступ к защищенному контенту. Другой способ сделать это, конечно, - это одна роль для каждого шаблона URL-адреса и предоставить людям несколько ролей.
Во всяком случае, ответ на ваш вопрос (или, по крайней мере, на вопрос, который, как я думаю, вы спрашиваете), заключается в том, что обычным делом является один компонент верхнего уровня на одну роль, защищающий все ресурсы с теми же ограничениями безопасности. Конечно, вы также группируете функциональные возможности в этом префиксе пути, поэтому некоторые люди ненавидят эту структуру, и некоторые люди просто предпочитают использовать аннотации в коде. Мне нравится моя безопасность, где я вижу ее в одном месте и могу легко сказать, что ожидания безопасности - это просто посмотреть URL.
Ответ 3
Конфигурация SpringSecurity зависит от выбранной вами аутентификации для вашего приложения: Например, для проверки подлинности формы вы хотите настроить URL-адрес успеха входа и выхода из системы без разрешения:
<http realm="Contacts Realm">
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
<logout logout-success-url="/index.jsp"/>
</http>
В случае базовой проверки подлинности у вас нет URL входа и выхода из системы, и конфигурация проще:
<http realm="Contacts Realm">
<intercept-url pattern="/**" access="ROLE_USER"/>
<http-basic/>
</http>
В случае выбора базовой проверки подлинности используйте второй пример.
Ответ 4
Перехват URL-адреса может быть выполнен таким образом. Предположим, что ваши URL-адреса службы обслуживания начинаются с /rest/
.
<http auto-config="true" use-expressions="true" access-denied-page="/accessDeniedPageURL">
<intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/view/products" access="isFullyAuthenticated()"/>
<form-login login-page="/landing" default-target-url="/view/products" authentication-failure-handler-ref="authenticationFailureHandler"/>
<logout invalidate-session="true" logout-success-url="/landing" delete-cookies="JSESSIONID"/>
<session-management invalid-session-url="/landing" session-authentication-error-url="/landing?msg=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/landing?msg=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
</http>
Ответ 5
Да, довольно часто задавать несколько шаблонов перехвата-url, а затем добавлять аннотации сверху, чтобы дополнительно ограничить определенные ресурсы.
Вы также можете использовать каталог для каждого ограничения, поэтому вам не понадобятся аннотации. Ex./user/** требует ROLE_USER,/admin/** требует ROLE_ADMIN и т.д.
Имейте в виду, когда вы используете любой метод, как он влияет на вашу безопасность, если вы допустили ошибку.
Если вы используете URL-адрес перехвата, вы должны поместить строки в правильном порядке, например:
<intercept-url pattern="/**" access="permitAll"/>
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/>
Не будет работать, потому что вы решете весь доступ в первой строке, так что строки должны быть отменены. Если начинающий работает над вашим проектом и меняет границы, это может быть большой проблемой.
Если вы используете аннотации, вы можете удалить строку аннотации по ошибке, оставив в своем приложении отверстие для безопасности.
@PreAuthorize("hasRole('ROLE_USER')")
Если вы повторно используете класс контроллера между двумя проектами, и в одном проекте вы хотите разрешить ROLE_USER всем методам внутри контроллера, в то время как для другого проекта, использующего общий код, требуется ROLE_ADMIN, тогда самый простой способ достичь этого является использование intercept-url.
Так что имейте в виду, @PreAuthorize будет жестко закодирован и распространен среди проектов. Вы можете расширить классы и добавить разные @PreAuthorize для каждого проекта, но это добавляет дополнительную сложность.
Мне нравится использовать intercept-url для защиты всей области, например /user/ **, потому что риск удаления аннотации меньше по ошибке.
Если мне нужно добавить мелкозернистый доступ, я добавляю аннотацию к методу в контроллере, который уже защищен перехватом-url, но это происходит очень редко.
Ответ 6
Spring Безопасность обычно хороша для доступа на основе ролей. и что об этом. Вы можете создать свой собственный ProcessFilter, чтобы сделать некоторые дополнительные вещи. Тем не менее, я считаю, что это большая работа для небольшого бенифита.
Альтернативой является использование перехватчиков запросов. В нескольких проектах для служб RESTful, использующих Spring MVC, я использую Interceptors Request для завершения некоторой аутентификации вне основного доступа к ролям. Это работает, и, на мой взгляд, намного проще отслеживать цепочку событий, но если вы имеете дело с тысячами транзакций в минуту, это может заглушить запросы.