Пользовательский AccessDecisionManager работает неожиданно - PullRequest
0 голосов
/ 18 июня 2019

У меня есть приложение Spring Boot, которое использует Spring Security для аутентификации и авторизации.Фаза авторизации требует пользовательского AccessDecisionVoter поверх стандартной авторизации на основе полномочий.Вот мои настройки:

@Override
    protected void configure(HttpSecurity http) throws Exception {

        ...

        http.authorizeRequests()
                .requestMatchers(getMatcherForAuthority1Urls())
                .hasAuthority("AUTHORITY1")
        .and().authorizeRequests()
                .requestMatchers(getMatcherForAuthority2Urls())
                .hasAuthority("AUTHORITY1")
        .and().authorizeRequests()
                .requestMatchers(getMatcherForAuthorities1and2Urls())
                .hasAnyAuthority("AUTHORITY1", "AUTHORITY1");

        http.authorizeRequests()
                .regexMatchers(REGEX_PATTERN_URLS_THAT_NEED_AUTHORISATION).authenticated()
                .accessDecisionManager(myAccessDecisionManager());

        http.authorizeRequests()
                .antMatchers(LOGIN_URL).permitAll();
    }

    @Bean
    public AccessDecisionManager myAccessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters
                = Arrays.asList(
                new WebExpressionVoter(), // votes for authorities
                myAccessVoter);           // my custom voter

        return new UnanimousBased(decisionVoters);
    }

Мои ожидания таковы:

  1. некоторые URL-адреса доступны только пользователям с полномочиями1, некоторые только пользователям с полномочиями2, а некоторые другие URL-адреса могут бытьДоступ к пользователям с любым полномочием.Это настройка в первом разделе метода configure ().
  2. На некоторых конкретных URL-адресах, определенных регулярным выражением, в дополнение к авторизации полномочиями также будет выполняться пользовательский AccessDecisionManager, который включает в себя пользовательского избирателя..

Что действительно происходит при запуске приложения, так это то, что пользовательский избиратель всегда выполняется независимо от URL-адреса запроса.Однако, если я удалю начальную часть метода configure (), чтобы не была настроена авторизация hasAuthority (), пользовательский избиратель будет выполняться только по URL-адресам, которые соответствуют регулярному выражению.

Тот же тип нежелательного поведения возникает при использовании:

http.authorizeRequests().anyRequest().authenticated();

перед настройкой пользовательского AccessDecisionManager.

Я явно допускаю некоторые ошибки при настройке этого.Разве пользовательский избиратель не должен всегда работать ТОЛЬКО на URL-адресах, которые соответствуют шаблону "REGEX_PATTERN_URLS_THAT_NEED_AUTHORISATION"?

Спасибо!

1 Ответ

1 голос
/ 18 июня 2019

Компонент AccessDecisionManager, который вы регистрируете в .accessDecisionManager(...), совместно используется в вашем целом приложении Spring Security, поэтому в любое время необходимо принять решение об авторизации, то же самое UnanimousBasedМенеджер решений будет вызван, который в свою очередь вызывает вашего избирателя.

Так вот:

authorizeRequests()
    .requestMatchers(getMatcherForAuthorities1and2Urls())
        .hasAnyAuthority("AUTHORITY1", "AUTHORITY1");

вызовет тот же AccessDecisionManager для "matcherForAuthorities1and2Urls" как REGEX_PATTERN_URLS_THAT_NEED_AUTHORISATION:

authorizeRequests()          
    .regexMatchers(REGEX_PATTERN_URLS_THAT_NEED_AUTHORISATION).authenticated()
        .accessDecisionManager(myAccessDecisionManager());

Аналогично, включая http.authorizeRequests().anyRequest().authenticated()зарегистрирует совпадение, которое соответствует каждому запросу, и запрашивает тот же AccessDecisionManager для определения доступа.

Возможное решение

Возможно, один из способов достижения желаемого поведения - этопередайте REGEX_PATTERN_URLS_THAT_NEED_AUTHORISATION в вашего собственного избирателя через его конструктор и используйте его для создания RequestMatcher.Затем ваш избиратель может решить, будет ли он «голосовать» на основе запроса:

public int vote(Authentication authentication, FilterInvocation fi,
            Collection<ConfigAttribute> attributes) {

    if(!regexPatternMatcher.matches(fi.getRequest())) {
        return ACCESS_ABSTAIN;
    }
    // ...
}

...