Vários pontos de entrada no Spring Security

Vários pontos de entrada no Spring Security

*1. Visão geral *

Neste tutorial rápido, veremos como* definir vários pontos de entrada em um aplicativo Spring Security *.

Isso implica principalmente na definição de vários blocos http em um arquivo de configuração XML ou em várias instâncias HttpSecurity, estendendo a classe WebSecurityConfigurerAdapter várias vezes.

*2. Dependências do Maven *

Para o desenvolvimento, precisaremos das seguintes dependências:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>

As versões mais recentes de spring-boot-starter-security, spring-boot-starter-web , Https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-thymeleaf%22[spring-boot-starter-thymeleaf], https://search. maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-test%22[spring-boot-starter-test], https://search.maven.org/classic/#search % 7Cga% 7C1% 7Ca% 3A% 22spring-security-test% 22 [teste de segurança da primavera] pode ser baixado do Maven Central.

===* 3. Vários pontos de entrada *

====* 3.1 Vários pontos de entrada com vários elementos HTTP *

Vamos definir a principal classe de configuração que conterá uma fonte de usuário:

@Configuration
@EnableWebSecurity
public class MultipleEntryPointsSecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User
          .withUsername("user")
          .password(encoder().encode("userPass"))
          .roles("USER").build());
        manager.createUser(User
          .withUsername("admin")
          .password(encoder().encode("adminPass"))
          .roles("ADMIN").build());
        return manager;
    }

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

Agora, vejamos* como podemos definir vários pontos de entrada *em nossa configuração de segurança.

Vamos usar um exemplo orientado pela autenticação básica aqui e faremos bom uso do fato de que o* Spring Security suporta a definição de vários elementos HTTP * em nossas configurações.

Ao usar a configuração Java, a maneira de definir várias regiões de segurança é ter várias classes _ @ Configuration_ que estendem a classe base WebSecurityConfigurerAdapter - cada uma com sua própria configuração de segurança. Essas classes podem ser estáticas e colocadas dentro da configuração principal.

A principal motivação para ter vários pontos de entrada em um aplicativo é se existem diferentes tipos de usuários que podem acessar partes diferentes do aplicativo.

Vamos definir uma configuração com três pontos de entrada, cada um com diferentes permissões e modos de autenticação:

  • um para usuários administrativos usando autenticação básica HTTP

  • um para usuários regulares que usam autenticação de formulário *e um para usuários convidados que não exigem autenticação

O ponto de entrada definido para usuários administrativos protege URLs do formulário /admin/* * _ para permitir apenas usuários com uma função de ADMIN e requer autenticação básica HTTP com um ponto de entrada do tipo _BasicAuthenticationEntryPoint que é definido usando o método _authenticationEntryPoint () _ :

@Configuration
@Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().hasRole("ADMIN")
            .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint());
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint(){
        BasicAuthenticationEntryPoint entryPoint =
          new BasicAuthenticationEntryPoint();
        entryPoint.setRealmName("admin realm");
        return entryPoint;
    }
}

A anotação _ @ Order_ em cada classe estática indica a ordem na qual as configurações serão consideradas para encontrar uma que corresponda à URL solicitada. *O valor order para cada classe deve ser exclusivo.

O bean do tipo BasicAuthenticationEntryPoint requer que a propriedade realName esteja configurada.

====* 3.2 Vários pontos de entrada, mesmo elemento HTTP *

Em seguida, vamos definir a configuração dos URLs do formulário _/user/* * _ que podem ser acessados ​​por usuários regulares com uma função de USUÁRIO usando autenticação de formulário:

@Configuration
@Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/user/**")
            .authorizeRequests().anyRequest().hasRole("USER")
            .and()
           //formLogin configuration
            .and()
            .exceptionHandling()
            .defaultAuthenticationEntryPointFor(
              loginUrlauthenticationEntryPointWithWarning(),
              new AntPathRequestMatcher("/user/private/**"))
            .defaultAuthenticationEntryPointFor(
              loginUrlauthenticationEntryPoint(),
              new AntPathRequestMatcher("/user/general/**"));
    }
}

Como podemos ver, outra maneira de definir pontos de entrada, além do método authenticationEntryPoint (), é usar o método defaultAuthenticationEntryPointFor () _. Isso pode definir vários pontos de entrada que correspondem a diferentes condições com base em um objeto _RequestMatcher.

A interface RequestMatcher possui implementações baseadas em diferentes tipos de condições, como caminho correspondente, tipo de mídia ou regexp. Em nosso exemplo, usamos o AntPathRequestMatch para definir dois pontos de entrada diferentes para URLs dos formulários /user/private/* e /user/general/