SpringBoot 1.5.x + Безопасность + OAuth2

У меня есть Spring Boot REST API с защитой OAuth2.

Сегодня я обновил мою версию spring-boot-starter-parent от 1.4.2 до 1.5.2.

Изменения полностью смутили меня.

Раньше я мог тестировать свой REST API с Postman. Когда мой токен доступа был неправильным или у меня не было прав на определенные ресурсы, ответ сервера был следующим:

{
  "error": "access_denied",
  "error_description": "Access is denied"
}

Теперь он перенаправляет меня на страницу /login... Когда я вхожу в систему - он показывает мой ресурс без аутентификации OAuth2...

Я попытался отключить его, и я нашел это волшебное свойство:

security.oauth2.resource.filter-order = 3

Эта строка отключена, перенаправляется на страницу входа.

Однако мои вопросы:

  • что произошло между этими 2 релизами с точки зрения безопасности?
  • эта "странная" строка является единственным допустимым исправлением?
  • Какова цель этой страницы входа и какая она используется (я проверил запросы и ответы в Google Chrome, и я не вижу никаких токенов доступа и файлов oauth2, поэтому он использует только репозиторий пользователя?)

Некоторые более важные части моего кода:

pom.xml

<!--- .... -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
</parent>
<properties>
    <!--- .... -->
    <spring-security-oauth.version>2.1.0.RELEASE</spring-security-oauth.version>
    <!--- .... -->
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Monitor features -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>
    <!-- Security + OAuth2 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>${spring-security-oauth.version}</version>
    </dependency>
<!--- .... -->

application.properties

#other properties
security.oauth2.resource.filter-order = 3

OAuth2.java

public class OAuth2 {
@EnableAuthorizationServer
@Configuration
@ComponentScan
public static class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManagerBean;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("trusted_client")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManagerBean).userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }
}

@EnableResourceServer
@Configuration
@ComponentScan
public static class ResourceServer extends ResourceServerConfigurerAdapter {

    @Autowired
    private RoleHierarchy roleHierarchy;

    private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
        DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy);
        return defaultWebSecurityExpressionHandler;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().expressionHandler(webExpressionHandler())
                .antMatchers("/api/**").hasRole("DEVELOPER");
    }
}
}

Security.java

@EnableWebSecurity
@Configuration
@ComponentScan
public class Security extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Bean
public JpaAccountDetailsService userDetailsService(AccountsRepository accountsRepository) {
    return new JpaAccountDetailsService(accountsRepository);
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
}
}

Ответ 1

Хорошо, я понял это сейчас.

@Клето Гадельха указал мне очень полезную информацию.

Тем не менее, я думаю, что примечание к выпуску довольно неясное или отсутствует какая-либо информация Помимо того, что фильтр ресурсов OAuth2 изменен с 3 на SecurityProperties.ACCESS_OVERRIDE_ORDER - 1, важной информацией является то, что порядок WebSecurityConfigurerAdapter умолчанию WebSecurityConfigurerAdapter 100 (источник).

Итак, до выпуска 1.5.x порядок сервера ресурсов OAuth2 был 3, который имел более высокий приоритет, чем WebSecurityConfigurerAdapter.

После выпуска 1.5.x порядок сервера ресурсов OAuth2 устанавливается равным SecurityProperties.ACCESS_OVERRIDE_ORDER - 1 (я думаю, это Integer.MAX_VALUE - 8), который теперь определенно имеет более низкий приоритет, чем базовый порядок WebSecurityConfigurerAdapter.

Поэтому после входа с 1.4.x в 1.5.x у меня появляется страница входа.

Итак, более элегантное решение в стиле java - установить @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) в классе WebSecurityConfigurerAdapter

Ответ 2

Ответ на ваш первый и второй вопрос: Spring Примечания к выпуску версии 1.5:

Фильтр ресурсов OAuth 2

Порядок по умолчанию для фильтра ресурсов OAuth2 изменился с 3 на SecurityProperties.ACCESS_OVERRIDE_ORDER - 1. Это помещает его после конечных точек исполнительного механизма, но до основной цепи фильтра аутентификации. Значение по умолчанию можно восстановить, установив security.oauth2.resource.filter-order = 3

Страница/login - это только путь, по которому spring перенаправляет неавторизованных пользователей. Поскольку вы не используете пользовательскую форму входа в систему, а ваш фильтр Oauth2 находился в неправильном положении, возможно, использовал Basic Auth.

Ответ 3

Это может быть связано с неправильной настройкой сервера ресурсов.

@Override
  public void configure(final HttpSecurity http) throws Exception {
    // @formatter:off
    http.csrf().disable().authorizeRequests()
    // This is needed to enable swagger-ui interface.
    .antMatchers("/swagger-ui.html","/swagger-resources/**","/webjars/**", "/v2/api-docs/**").permitAll()
    .antMatchers("/api/v1/**").hasRole("TRUSTED_CLIENT")
    .antMatchers("/api/v1/**").hasRole("USER")
    .antMatchers("/api/v1/**").hasAuthority("ROLE_TRUSTED_CLIENT");
    // @formatter:on
  }