Spring Security — роли, недоступные в HttpServletRequest, если не указаны через mappableAuthorities

#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> теге в tomcat server.xml .

2. Это невозможно, HttpServletRequest у него нет метода для извлечения ролей, вот почему Spring Security нуждается в таком сопоставлении. Можно только спросить HttpServletRequest.isUserInRole , доступна ли определенная роль. Если вы найдете способ получить все роли HttpServletRequest , вы можете использовать этот способ в своем собственном MappableAttributesRetriever .