#java #spring #spring-security
#java #весна #spring-безопасность
Вопрос:
У меня есть веб-приложение Spring Boot, которое запускается на сервере приложений Tomcat и проходит проверку подлинности на стороннем IdP.
В настоящее время мы выполняем аутентификацию на основе ролей в ряде наших приложений, используя <security-role>
и <security-constraint>
в a web.xml
, и она работает должным образом.
Теперь, пытаясь использовать Spring Security, я добавил следующий класс конфигурации:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
String[] publicPaths = /*get public paths from properties*/
String[] authorizedPaths = /*get authorized paths from properties*/
String[] authorizedRoles = /*get authorized roles from properties*/
http.csrf().disable()
.jee()
.mappableAuthorities(authorizedRoles)
.and()
.authorizeRequests()
.antMatchers(publicPaths).permitAll()
.antMatchers(authorizedPaths).hasAnyRole(authorizedRoles)
.and()
.logout().disable()
;
}
}
authorizedRoles
В приведенной выше конфигурации указаны роли, которым разрешен доступ к этому приложению. Однако в приложении есть другие ручные проверки, которые просто вызываются HttpServletRequest.isUserInRole()
, чтобы определить, имеет ли пользователь определенную роль. Перед использованием Spring Security этот вызов возвращался true
, если у этого пользователя была эта роль в исходном запросе. После добавления Spring Boot этот вызов возвращается только true
в том случае, если роль является одной из тех, которые были переданы .mappableAuthorities()
в примере выше. Роли, которые проверяются с помощью HttpServletRequest.isUserInRole()
, хранятся в базе данных и могут часто обновляться, поэтому передача их .mappableAuthorities()
при загрузке приложения невозможна.
Итак, чтобы перейти к сути моего вопроса, похоже, что Spring Security изменяет оригинал HttpServletRequest
и удаляет любые роли, которые не содержатся в authorizedRoles
переданном .mappableAuthorities()
.
Есть ли способ избежать такого поведения или, возможно, передать какой-то подстановочный .mappableAuthorities()
знак, чтобы вам не нужно было знать все роли при запуске приложения, чтобы они были доступны через вызов HttpServletRequest.isUserInRole()
? Я часами просматривал документацию по безопасности Spring и ничего не нашел.
Ответ №1:
Вы можете видеть только сопоставленные роли, потому SecurityContextHolderAwareRequestFilter
что обертывает HttpServletRequest
:
Фильтр, который заполняет ServletRequest оболочкой запроса, которая реализует методы безопасности servlet API.
Он использует SecurityContextHolderAwareRequestWrapper
для реализации методов безопасности servlet API:
Spring Security-aware
HttpServletRequestWrapper
, который использует определенныйSecurityContext
Authentication
объект для реализации методов безопасности servlet API:
getUserPrincipal()
isUserInRole(String)
HttpServletRequestWrapper.getRemoteUser()
.
Чтобы настроить сопоставление ролей, см. J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
:
Реализация AuthenticationDetailsSource, которая преобразует роли пользователя J2EE (полученные при вызове
HttpServletRequest.isUserInRole(String)
) вGrantedAuthority
s и сохраняет их в объекте сведений об аутентификации.
Он использует a MappableAttributesRetriever
для получения сопоставляемых ролей:
Интерфейс, который будет реализован классами, которые могут извлекать список отображаемых строк атрибутов безопасности (например, список всех доступных ролей J2EE в веб-приложении или EJB).
Вы можете написать свой собственный MappableAttributesRetriever
, который загружает отображаемые роли из вашей базы данных.
Или вы можете использовать WebXmlMappableAttributesRetriever
, который извлекает роли из web.xml
:
Эта
MappableAttributesRetriever
реализация считывает список определенных ролей J2EE из web.xml файл и возвращает их изgetMappableAttributes()
.
Комментарии:
1. Но это не решит проблему. Редактору
MappableAttributesRetriever
по-WebXmlMappableAttributesRetriever
прежнему необходим список всех отображаемых ролей, независимо от того, поступает ли он из базы данных или откуда-либо еще. Я хочу, чтобы он учитывал все роли в запросе, какими бы они ни были. Я полагаю, что в других наших приложениях это достигается путем указанияallRolesMode
атрибута в<Realm>
теге в tomcatserver.xml
.2. Это невозможно,
HttpServletRequest
у него нет метода для извлечения ролей, вот почему Spring Security нуждается в таком сопоставлении. Можно только спроситьHttpServletRequest.isUserInRole
, доступна ли определенная роль. Если вы найдете способ получить все ролиHttpServletRequest
, вы можете использовать этот способ в своем собственномMappableAttributesRetriever
.