Segurança de Aplicação Web com Spring Security

Criptografia, autenticação de usuário, autorização de acesso é um tema complicado para quem está começando os estudos de Spring Boot e se depara com segurança de aplicações web. Spring Security traz muita facilidade a nível de uso, mas isso não significa que é simples de entender. Por isso, resolvi criar este artigo que é tema de aula do curso Java Hospitalar.

Para começarmos, você precisa aprender três conceitos:

  • Autenticação
  • Autorização
  • Criptografia

Autenticação é simples, afinal, todos usamos todos os dias. É aquela velha tela de que requisita dados de acesso, tal como, nome de usuário e senha.

Autorização é um segundo nível de segurança, onde você dá a cada usuário um perfil, e esse perfil controla o que ele pode e não pode acessar.

A criptografia serve para proteger as suas credenciais de acesso que neste caso, vamos nos referir a senha do usuário. Existem vários tipos, mas para este artigo vamos focar na Bcrypt que gera um hash da senha, e ao invés de salvar a senha no banco de dados, salvamos esse hash que é gerado por esse algoritmo.

Em um sistema hospitalar, estamos trabalhando com dados sensíveis de pacientes e profissionais. Onde um médico pode ter acesso aos dados do pacientes, assim como, a enfermeira que fará a triagem. Mas, o recepcionista não pode ter acesso aos dados desse paciente, além dos dados de cadastro, que são essenciais para a sua função. Isso se chama controle de acesso, que simplesmente chamamos de autorização.

Nesse sentido, cada pessoa que vai utilizar o sistema precisa ter um perfil de acesso que conta com:

  • Autenticação: Login + Senha
  • Autorização: Perfil de Acesso
  • Criptografia: Algoritmo de Segurança para Proteção de Senhas

Sendo assim, cada profissional terá o seu perfil, como veremos abaixo:

  • Médico: Perfil Medico
  • Enfermeiro: Perfil Enfermeiro
  • Recepcionista: Perfil Recepcionista
  • Administrador: Perfil Admin

O Admin tem acesso a tudo, enquanto o Médico tem acesso a prontuário dos pacientes. A enfermeira tem acesso as dados das aferições e anamneses do paciente. O recepcionista tem acesso apenas a tela de cadastro e os dados de registros de outros entradas desse paciente na unidade. Ou seja, estamos restringindo o acesso.

Mas, sei que você já deve estar doido para ver como o Spring Security faz isso na prática. Vamos lá?

Trago agora, um trecho de código deste projeto:

package com.hospital.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/admin/**").hasAuthority("ADMIN")
                .requestMatchers("/recepcionista/**").hasAuthority("RECEPCIONISTA")
                .requestMatchers("/medico/**").hasAuthority("MEDICO")
                .requestMatchers("/enfermeiro/**").hasAuthority("ENFERMEIRO")
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .formLogin(login -> login
                .loginPage("/login")  // Rota personalizada para a página de login
                .defaultSuccessUrl("/", true) // Redireciona após login bem-sucedido
                .permitAll()  // Permite que todos acessem a página de login
            )
            .logout(logout -> logout
                .logoutUrl("/logout")  // Rota para logout
                .logoutSuccessUrl("/login?logout")  // Redireciona após logout
                .invalidateHttpSession(true)  // Invalida a sessão
                .deleteCookies("JSESSIONID")  // Remove cookies
            );

        return http.build();
    }
}

1. Definição da Classe

@Configuration
public class SecurityConfig {
A anotação @Configuration indica que essa classe define configurações para o Spring. Ela será carregada automaticamente no contexto da aplicação.

2. Método securityFilterChain

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  • O método retorna um SecurityFilterChain, que é a configuração de segurança da aplicação.
  • @Bean permite que o Spring gerencie essa configuração e a utilize onde necessário.
  • HttpSecurity é a classe principal usada para configurar segurança baseada em web.

3. Desativando CSRF

.csrf(csrf -> csrf.disable())
  • O CSRF (Cross-Site Request Forgery) é uma proteção contra ataques que exploram a autenticação do usuário em aplicações web.
  • Aqui, ele está desativado. Isso pode ser útil para APIs REST stateless, mas para aplicações web tradicionais, o ideal seria mantê-lo ativado e configurado corretamente.

4. Configuração de Autorizações

.authorizeHttpRequests(auth -> auth
    .requestMatchers("/admin/**").hasAuthority("ADMIN")
    .requestMatchers("/recepcionista/**").hasAuthority("RECEPCIONISTA")
    .requestMatchers("/medico/**").hasAuthority("MEDICO")
    .requestMatchers("/enfermeiro/**").hasAuthority("ENFERMEIRO")
    .anyRequest().authenticated()
)

Aqui definimos regras de autorização, ou seja, quem pode acessar quais URLs:

  1. requestMatchers("/admin/**").hasAuthority("ADMIN")
    • Apenas usuários com a autoridade “ADMIN” podem acessar qualquer URL que comece com /admin/.
  2. requestMatchers("/recepcionista/**").hasAuthority("RECEPCIONISTA")
    • Apenas usuários com “RECEPCIONISTA” podem acessar /recepcionista/.
  3. requestMatchers("/medico/**").hasAuthority("MEDICO")
    • Apenas usuários com “MEDICO” podem acessar /medico/.
  4. requestMatchers("/enfermeiro/**").hasAuthority("ENFERMEIRO")
    • Apenas usuários com “ENFERMEIRO” podem acessar /enfermeiro/.
  5. anyRequest().authenticated()
    • Qualquer outra requisição exige um usuário autenticado

5. Política de Sessão

.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  • Define a política de gerenciamento de sessões como STATELESS.
  • Isso significa que o Spring Security não armazenará informações da sessão do usuário.
  • Esse comportamento é comum em APIs REST, onde a autenticação é feita via tokens (JWT) ao invés de sessões HTTP tradicionais.

6. Configuração de Login

.formLogin(login -> login
    .loginPage("/login")  // Rota personalizada para a página de login
    .defaultSuccessUrl("/", true) // Redireciona após login bem-sucedido
    .permitAll()  // Permite que todos acessem a página de login
)
  • Habilita a autenticação baseada em formulário.
  • Define /login como a página de login personalizada.
  • Após o login bem-sucedido, o usuário é redirecionado para / (página inicial).
  • .permitAll() permite que qualquer pessoa acesse a página de login, sem precisar estar autenticada.

7. Configuração de Logout

.logout(logout -> logout
    .logoutUrl("/logout")  // Rota para logout
    .logoutSuccessUrl("/login?logout")  // Redireciona após logout
    .invalidateHttpSession(true)  // Invalida a sessão
    .deleteCookies("JSESSIONID")  // Remove cookies
)
  • Define /logout como a URL para fazer logout.
  • Após o logout, o usuário é redirecionado para /login?logout.
  • invalidateHttpSession(true): Invalida a sessão atual, removendo os dados do usuário.
  • deleteCookies("JSESSIONID"): Remove o cookie de sessão, garantindo que o usuário precise fazer login novamente.

8. Resumo

Essa configuração faz o seguinte:

  • Define restrições de acesso com base nas autoridades dos usuários.
  • Exige autenticação para qualquer outra rota.
  • Configura autenticação baseada em formulário com uma página de login personalizada.
  • Implementa logout com invalidação de sessão e remoção de cookies.
  • Define uma política de sessão stateless, útil para APIs.

9. Curso Java Hospitalar

O Curso Java Hospitalar está em desenvolvimento e já consta com as aulas de preparação de ambiente de desenvolvimento, usando Spring Boot 3.4.4, Java JDK 21, Intellij Idea Community, MySQL 8.0.41, Git e Github do Projeto, as aulas de criação do projeto usando Spring Initializr, as aulas de criação das entidades, mapeamento objeto relacional (ORM), explicação detalhada do passo a passo utilizado, potencializando ainda mais seu estudo com inteligência artificial (chatgpt), e material complementar de aprofundamento, tal como, este artigo.

Como o objetivo do curso é ser um sistema de prontuário eletrônico e ainda estou gravando as aulas, semanalmente, você pode adquirir este curso por um valor promocional, com acesso vitalício, direito a certificado e suporte, através deste link: https://pay.kiwify.com.br/P54A393

Observação: Como este curso é avançado e inteiramente prático, o ideial seria que você tivesse a base de orientação a objetos, uso de Java, e pelo menos o básico de Spring Boot. Por isso, deixarei os cursos Java na Prática e Spring Boot na Prática, ao final da página deste link, para que você possa adquirir em conjunto se desejar, ou comprá-los isoladamente para se preparar para algo mais avançado, nos links abaixo:

Caso queira conhecer os demais cursos de Java, acesse os links abaixo:

Observação: Você pode comprar mais de um curso, aproveitando a promoção dos links acima. Aqui, quando você decide adquirir um treinamento, no final da página, oferto os outros cursos por um valor especial. Espero que goste.

Bons estudos.

Sucesso na carreira como programador.

Fala, Dev! Vou falar um pouco sobre mim em três vertentes (Estudos acadêmicos, trabalho e vida pessoal), vamos lá?! Na parte acadêmica, sou graduado em ciência da computação, técnico em redes de computadores e especializado em segurança da informação. Trabalho com tecnologia há mais de 6 anos, focado em ambientes de saúde pública municipal. Já atuei como gerente de tecnologia da unidade de pronto atendimento da região e como técnico de informática da secretaria de saúde. Neste período, tive a oportunidade de trabalhar com sistemas hospitalares, ambulatoriais, dentre outros, que fomentaram o desejo de ingressar na área de programação, pois na época, meu trabalho era mais focado em gestão e suporte técnico. Minha linguagem de programação favorita é Java. Mas, já atuei com outros linguagens, tal como, Python, C++, JavaScript, tanto no back-end, quanto no front-end, até mesmo, a criação de scripts com Shell Script. Sou natural de Maceió, AL. Onde atualmente moro na cidade de Palmeira dos Índios, interior do estado. Estou 31 anos, sou casado e minha primeira filha está prestes a nascer, Maria Sofia. Comecei a trabalhar com produção de conteúdo com o objetivo de ensinar jovens e adultos a programar, e essa vontade se transformou em um projeto, onde hoje aplico na forma de treinamentos online, seja ao vivo por aplicativos de reunião, vídeos e lives no youtube, e cursos digitais ofertados nas plataformas da Kiwify e Udemy, onde já passo dos 1.500 alunos. Comecei com um projeto simples, mas está tomando formato de escola de tecnologia, onde tenho o desejo de treinar cada vez mais pessoas, para ingressar neste mundo o mais rápido possível. Seja bem-vindo ao meu Mundo.

1 comentário

Publicar comentário