Spring Безопасность, конечные косые черты и точки в URL-адресах

Я использую Spring Security 3.1.4 для защиты приложения Spring MVC 3.2.4, развернутого в Tomcat. У меня есть следующая конфигурация безопасности Spring:

<http auto-config="true" use-expressions="true">
   <http-basic />
   <logout ... />
   <form-login ... />

   <intercept-url pattern="/" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/login" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/under-construction" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/admin-task*" access="hasRole('ROLE_USER') and hasRole('ROLE_ADMINISTRATOR')" />
   <intercept-url pattern="/resources/**" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>

Я заметил, что шаблоны URL без конечной косой черты (например, /about) не соответствуют URL-адресам с завершающей косой чертой (например, /about/) и наоборот. Другими словами, URL-адрес с косой чертой и идентичный URL-адрес без косой черты рассматриваются как два разных URL-адреса с помощью Spring Security. Проблема может быть устранена с помощью двух правил безопасности:

<intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
<intercept-url pattern="/about/" access="isAnonymous() or hasRole('ROLE_USER')" />

Есть ли лучшее решение?

Я знаю, что path-type="regex" позволяет определять шаблоны URL с регулярными выражениями, но я хотел бы избежать любой ненужной сложности, если это возможно.

Обновление

Как отметил Адам Гент, есть дополнительная проблема, которая включает URL-адреса с точкой: /about.foo и /about рассматриваются как один и тот же URL-адрес Spring MVC. Однако Spring Security рассматривает их как два разных URL-адреса. Таким образом, может потребоваться еще одно правило безопасности:

<intercept-url pattern="/about.*" .../>

Ответы

Ответ 1

Spring Безопасность 4.1 +

Spring Теперь Security добавила новый соединитель, который знает вашу конфигурацию, соответствующую URL-адресу Spring MVC. Это сообщает Spring Security для соответствия путям на основе тех же правил, что использует Spring MVC, исключая возможность действительного URL-адреса, но необеспеченного.

Сначала вам нужно заменить старых помощников новым совпадением MVC. Spring Безопасность теперь синхронизирована, однако вы настроили Spring MVC, чтобы вы могли добавлять или удалять любую конфигурацию, соответствующую пути. Я рекомендую придерживаться стандартных по умолчанию.

Конфигурация Java

Если вы использовали antMatchers, теперь вы должны использовать mvcMatchers:

protected configure(HttpSecurity http) throws Exception {
  http.authorizeRequests()
        .mvcMatchers("/about").hasRole("USER");
}

Конфигурация XML

Вам нужно добавить атрибут request-matcher в тэг http:

<http request-matcher="mvc">
  <intercept-url pattern="/about" access="hasRole('USER')"/>
</http>

Полная ссылка

Обратите внимание, что вы также больше не должны префиксать свои роли с помощью "ROLE_" как Spring Безопасность делает это для вас автоматически.


Spring Безопасность до 4.1

Мне не удалось найти способ обработки как суффикса конечной косой черты, так и суффиксов пути в Spring Security. Очевидно, что для обработки этих случаев можно написать регулярное выражение, но это, по-видимому, делает правила безопасности слишком сложными и подвержен ошибкам. Я хочу быть настолько уверенным, насколько возможно, что я не подвергаю ресурсы случайно.

Поэтому мой подход состоит в том, чтобы отключить это поведение в Spring, сконфигурировав совпадение пути как строгий как с косой чертой, так и с суффиксами.

Конфигурация Java

@Configuration
public class ServletConfig extends WebMvcConfigurerAdapter {
  @Override
  public void configurePathMatch(final PathMatchConfigurer configurer) {
    configurer.setUseSuffixPatternMatch(false);
    configurer.setUseTrailingSlashMatch(false);
  }
}

Конфигурация XML

<mvc:annotation-driven>
  <mvc:path-matching suffix-pattern="false" trailing-slash="false" />
</mvc:annotation-driven>

Ответ 2

<intercept-url pattern="/about/**"...

также работает для меня в Spring Security 3.1.4. Это обеспечивает /about, /about/ и /about/anything_else