Você já teve sua sessão inspirada em algum site? Sabe por que isso acontece? Neste curso, vamos explorar bastante o tema das sessões e também como fazer autenticação em sites com Java Web. Este curso será ministrado pela Iasmin Araújo, instrutora da Escola de Programação.
Audiodescrição: Iasmin se considera uma mulher branca, com cabelo castanho escuro longo e olhos verdes. Ela usa uma blusa rosa e, ao fundo, vemos uma parede branca e uma porta fechada, ambas iluminadas por uma luz azulada.
Neste curso, vamos aprender a criar uma camada de segurança na aplicação web utilizando o Spring Security. Também vamos explorar vários beans (componentes) de configuração do Spring Security em profundidade.
Além disso, conseguiremos configurar diferentes usuários da aplicação. Esses perfis poderão fazer login, logout e visualizar várias informações de usuário.
Além disso, vamos conhecer vários ataques que são feitos na web e como nos protegermos deles. Utilizaremos boas práticas de segurança para garantir um desenvolvimento seguro das aplicações. Por fim, entenderemos como o Thymeleaf conversa com o Spring Security para adicionar proteção às nossas páginas web.
Vamos ver tudo isso no projeto da Clínica VollMed. Nesse projeto, lidamos com os dados de médicos e de consultas. Esses dados, a princípio, são acessados por atendentes.
Inicialmente, a aplicação não possui uma camada de segurança, mas, ao longo do curso, evoluímos o projeto para incluir essa camada.
A primeira página com a qual um usuário tem contato é a página de login, que possui os campos de e-mail e senha. Por exemplo, temos o usuário João, cadastrado no banco de dados, com o e-mail "joao@exemplo.com".
Ele pode entrar com a senha "joao123". Após clicar para entrar, somos redirecionados ao site. No site, também adicionamos a opção de conversar com o João. No menu "Olá João", podemos clicar no botão "Sair", e ao fazer isso, somos redirecionados para uma página informando que saímos da aplicação.
Para aproveitar melhor este curso, é importante que já tenhamos assistido à formação de Java e Spring Boot. Todos os conhecimentos adquiridos lá serão muito úteis.
É importante realizar todas as atividades e consultar todos os materiais complementares disponibilizados ao longo do curso. Caso surja alguma dúvida ou dificuldade, sinta-se à vontade para enviar no Fórum e conversar com outras pessoas que estão fazendo o curso.
Vamos começar o nosso desenvolvimento?
Neste curso, trabalharemos com um projeto da Clínica Médica VollMed. Inicialmente, este projeto será acessado apenas por atendentes da clínica. Essas pessoas poderão cadastrar profissionais, registrar consultas e também visualizar quais são os médicos, as médicas e as consultas da clínica.
Trata-se de um projeto em Java Web, no qual não utilizamos uma API, mas uma aplicação web com o auxílio do Thymeleaf. As páginas são renderizadas no navegador.
A aplicação está rodando localmente no endereço localhost:8080
, na página inicial (Home). Nesta página, há um texto de boas-vindas e o texto "Encontre profissionais de diversas especialidades e agende sua consulta com facilidade".
Além da página inicial, temos uma página para visualizar profissionais de medicina, onde também é possível cadastrar uma pessoa. O mesmo se aplica às consultas: podemos ver as consultas a partir de uma data específica e cadastrar novas consultas com base na especialidade médica.
Nossa aplicação está totalmente funcional, permitindo realizar cadastros com sucesso. No entanto, mesmo rodando localmente, em algum momento, o endereço localhost:8080
será substituído por um domínio próprio, como "www.clinicavollmed.com.br".
Imagine que uma pessoa que não é atendente da clínica tente acessar essa rota. Apenas digitando a rota padrão da página inicial, essa pessoa já consegue acessar nosso site e visualizar todos os dados médicos e de consultas, o que expõe dados sensíveis. Não queremos isso.
Por esse motivo, durante este curso, trabalharemos no projeto da Clínica VollMed para criar uma nova camada de proteção. Como estamos utilizando Java e Spring Boot, podemos adicionar uma camada de segurança com o Spring Security.
Para adicionar o Spring Security, acessaremos o site start.spring.io, onde baixamos todas as dependências dos nossos projetos.
No site, selecionamos o projeto Maven no topo esquerdo da página e, em seguida, clicamos no botão "Add Dependencies" na parte superior direita e digitamos "Security".
Selecionamos a primeira opção, que é o Spring Security. Em seguida, clicamos no botão "Explore" na parte de baixo da interface, que carrega o arquivo "pom.xml" da aplicação. Copiamos a primeira dependência gerada na tag Dependencies
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
No IntelliJ, onde a aplicação está rodando, colamos essa dependência no arquivo "pom.xml" do projeto, logo após a dependência do MySQL e antes da parte de testes.
Recarregamos a aplicação e o arquivo "pom.xml" clicando no ícone do Maven no topo direito da interface e selecionando "Stop and Rerun" no menu superior do Spring.
Após adicionar o Spring Security, ao recarregar a página no navegador, percebemos que não conseguimos mais acessar o localhost:8080
.
Fomos redirecionados para uma URL de login, que solicita um nome de usuário e uma senha. Como não configuramos nenhum usuário, verificamos no log da aplicação que o Spring Security gerou uma senha segura.
O Spring cria uma página padrão de login, considerando um único usuário chamado
user
. A senha desse usuário é a gerada no log.
Copiamos a senha gerada, voltamos ao navegador, colamos na parte de senha e utilizamos "user" como nome de usuário. Ao clicar em "Sign in", conseguimos acessar a aplicação.
Além da página de login, o Spring também fornece uma página de logout. Na barra de navegação, substituímos "?continue" na URL "localhost:8080/?continue" por "logout" para visualizar a página de confirmação de logout.
Trata-se de uma página com a pergunta "Are you sure you want to log out?", seguida do botão "Log Out". Ao confirmar que desejamos sair, saímos da aplicação e não conseguimos mais acessar URLs protegidas, como localhost:8080/medicos
.
Com isso, já temos uma camada de segurança construída pelo Spring, permitindo login e logout corretamente.
No entanto, o Spring nos alerta que a senha gerada deve ser usada apenas para desenvolvimento, e as configurações de segurança devem ser atualizadas antes de rodar a aplicação em produção.
Portanto, ao longo do curso, personalizaremos a aplicação para ter configurações de segurança adequadas à Clínica VollMed. Na sequência, iniciaremos essa personalização.
Conseguimos logar na nossa aplicação utilizando o usuário padrão ("user") e a senha gerada pela aplicação, uma senha aleatória que aparece no log.
No entanto, essa senha é generada novamente toda vez que reexecutamos a aplicação.
Se clicarmos em "Stop and Rerun", a aplicação reinicia e a senha será diferente da que estava cadastrada no momento do login. Isso gera um problema: toda vez que a equipe de desenvolvimento fizer alguma alteração, uma nova senha será gerada e precisará ser comunicada a toda a equipe de atendentes.
Além disso, todas as pessoas atendentes terão que compartilhar a mesma senha, o que pode complicar o gerenciamento das informações. Portanto, é interessante termos perfis separados para a nossa aplicação.
No log, a mensagem da senha gerada é criada pelo UserDetailsServiceAutoConfiguration
, responsável por gerar o usuário automático e realizar as configurações automáticas do Spring Security.
No entanto, queremos que nossos próprios usuários estejam cadastrados na aplicação. Para isso, precisamos criar uma classe de configuração para informar ao Spring como serão os nossos UserDetails
.
Vamos começar a criação da nossa classe. Fecharemos o pom.xml, onde mexemos anteriormente. Temos vários pacotes na nossa aplicação e, para criar a classe de configuração, podemos criar mais um pacote dentro da pasta "infra", pois não estamos tratando de classes específicas da aplicação relacionadas a domínio ou controlador, mas de algo que ocorre nos bastidores.
Dentro de "infra", criaremos um novo pacote relacionado à segurança usando o atalho "Alt + Insert" para abrir o menu "New" e clicando em "Package" e chamando-o de "security".
Dentro de "security", usaremos novamente o atalho "Alt + Insert" e criaremos uma nova classe ("Class") chamada "ConfiguracoesSegurança". Selecionaremos "Class" e, na mensagem que surge na tela, adicionaremos ao Git também clicando no botão "Add".
Precisamos informar ao Spring que esta é uma classe de configuração de segurança. Fazemos isso com duas anotações diferentes na classe. A primeira é @Configuration
, que indica ao Spring que esta é uma classe de configuração e que ela deve gerenciar essas configurações.
Além disso, ativaremos as configurações específicas de segurança com a anotação @EnableWebSecurity
, indicando que estamos tratando especificamente da segurança.
No log da aplicação, o UserDetailsServiceAutoConfiguration
não será mais utilizado; queremos nosso próprio UserDetailsService
. Para isso, criaremos um Bean que define como será nosso UserDetailsService
.
Utilizaremos @Bean
para indicar que este método está relacionado à configuração e retornaremos um UserDetailsService
. Declararemos o método como public UserDetailsService
e o chamaremos de dadosUsuariosCadastrados
.
Dentro deste método, criaremos nossos próprios usuários e retornaremos esses dados dentro do objeto UserDetailsService
.
Instanciaremos um usuário com UserDetails
, a interface específica do Spring Security para tratar dos usuários, e o chamaremos de usuario1
.
O usuario1
será um User.builder().username()
, que será o nome do nosso usuário. No caso, utilizaremos "joao@email.com"
para o atendente João, que deverá logar com o e-mail.
Passaremos também uma senha simples, "joao123", e utilizaremos .build()
para construir o usuário. Criamos um usuario1
e, para termos dois atendentes na nossa clínica, criaremos um usuario2
, copiando e colando o usuario1
e renomeando para usuario2
. O usuario2
será "maria@email.com"
e a senha será "maria123"
.
Esses usuários serão guardados em memória, pois não trabalharemos com um banco de dados por enquanto. Retornaremos uma implementação específica de UserDetailsService
que guarda esses dados na memória, utilizando return new InMemoryUserDetailsManager(usuario1, usuario2)
. Assim, temos dois usuários diferentes cadastrados.
@Configuration
@EnableWebSecurity
public class ConfiguracoesSeguranca {
@Bean
public UserDetailsService dadosUsuariosCadastrados(){
UserDetails usuario1 = User.builder()
.username("joao@email.com")
.password("joao123")
.build();
UserDetails usuario2 = User.builder()
.username("maria@email.com")
.password("maria123")
.build();
return new InMemoryUserDetailsManager(usuario1, usuario2, usuario3);
}
}
Teoricamente, configuramos a segurança e tudo que o Spring Framework, não apenas o Spring Security, faz é baseado em Beans e injeção de dependência.
Para configurar a segurança, trabalhamos com esses Beans. Neste caso, temos um método que retorna um UserDetailsService
, anotado com @Bean
, indicando que um dos objetos gerenciados pelo Spring será um UserDetailsService
com a implementação fornecida.
Podemos visualizar isso melhor no log. Após a configuração da senha, aparece uma linha indicando o r$InitializerUserDetailsManagerConfigurer
, configurado como Global AuthenticationManager
com um Bean UserDetailsService
chamado InMemoryUserDetailsManager
.
Esse Bean configurava o usuário "user", mas agora temos nosso próprio Bean. Ao recarregar a aplicação, teremos um novo Bean com o nome configurado, DadosUsuariosCadastrados
.
Ao reiniciar, a parte da senha gerada desaparece, pois sobrescrevemos essa configuração. O Bean UserDetailsService
aparece com o nome DadosUsuariosCadastrados
, confirmando a criação do nosso próprio Bean de configuração de segurança.
Vamos testar os usuários fazendo login na aplicação. Entraremos com "joao@email.com" e a senha "joao123". Ao tentar logar, a página de login apenas recarrega.
No IntelliJ, o log indica uma exceção: a senha não possui um PasswordEncoder. Se essa é a intenção, devemos usar o prefixo {noop}
.
O log sugere o uso de um PasswordEncoder, que é um codificador de senha que veremos mais adiante. Por enquanto, queremos entender como as senhas estão sendo salvas. Utilizaremos o prefixo {noop}
, que indica a ausência de um password encoder. Copiamos {noop}
e colamos dentro das aspas da string das senhas joao123
e maria123
.
UserDetails usuario1 = User.builder()
.username("joao@email.com")
.password("{noop}joao123")
.build();
UserDetails usuario2 = User.builder()
.username("maria@email.com")
.password("{noop}maria123")
.build();
Reiniciaremos a aplicação e recarregaremos a página de login. Após digitar "joao@email.com" e "joao123", clicamos em "Sign in". Agora, conseguimos acessar a aplicação com o login de João, configurado anteriormente.
Utilizamos um Bean para criar nossas próprias configurações de usuários e podemos criar outros Beans para personalizar a segurança da aplicação. Continuaremos a fazer isso em sequência.
O curso Java e Spring Security: proteja suas aplicações web possui 140 minutos de vídeos, em um total de 51 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.