Autenticação Basic com Java Spring
Alexandre Tannus
Posted on March 11, 2021
A autenticação de usuários é uma necessidade básica em boa parte das aplicações web e mobile. Realizar essa autenticação utilizando o framework Spring é fácil. Este artigo mostra como realizar a autenticação básica no Spring, com a criação de um servidor de recursos (Resource Server) e a configuração com o modelo Basic.
Introdução
A autenticação Basic é a forma mais simples de autenticar um usuário. Ela consiste na configuração de um servidor de recursos e a definição de um usuário e senha. O Spring possui essa autenticação embutida automaticamente no pacote spring-boot-starter-security
, ou seja, caso essa dependência seja adicionada ao projeto já é possível utilizar essa autenticação sem a necessidade de configurações adicionais.
No entanto, para definir usuários e senhas específicos para a aplicação é necessário que algumas configurações sejam adicionadas ao projeto.
Criação do projeto base
O projeto base pode ser criado utilizando qualquer ferramenta/IDE que permita a geração de projetos Spring. Algumas opções para realizar esta tarefa são:
- Spring Initializr
- IDE Spring Tool Suite (STS)
- Visual Studio Code com extensão Spring Tool
Na criação do projeto devem ser adicionadas as dependências
- Spring Boot Starter Web
- Spring Security
Para os testes da autenticação de rotas é necessário implementar um controlador simples. Este controlador proverá conteúdos estáticos, apenas para exemplificar o funcionamento.
@RestController
@RequestMapping("/main")
public class BasicController {
@GetMapping("protect")
public String protectedRoute() {
return "Rota Protegida";
}
@GetMapping("free")
public String unprotectedRoute() {
return "Rota Livre";
}
}
A princípio, as duas rotas estarão bloqueadas para acesso autenticado apenas. Após a configuração personalizada será possível liberar uma delas da autenticação e deixar a outra protegida.
Com essas duas dependências adicionadas uma configuração de segurança padrão é adicionada ao projeto utilizando o nome de usuário user
e uma senha aleatória que é mostrada no log de inicialização do sistema, conforme mostrado na figura a seguir
Além disso, o Spring provê automaticamente a seguinte página de login
A estilização desta página de login e sua correta configuração não estão no escopo deste artigo
O maior problema desta geração de senha padrão é que a cada reinicialização do sistema a senha será alterada, tornando essa configuração padrão inviável para ambiente de produção e muito difícil de gerenciar até em ambiente de desenvolvimento.
Configurando o usuário e senha através das propriedades
Algumas propriedades de configuração da aplicação podem ser definidas no arquivo application.properties
ou no arquivo application.yml
, assim como via linha de comando. Dentre estas propriedades estão o usuário e senha para a autenticação Basic. Um exemplo de configuração é mostrado a seguir, com a alteração do nome do usuário para alexandre
e a senha para 123456
spring.security.user.name=alexandre
spring.security.user.password=123456
A figura a seguir é um print da tela do Insomnia, uma ferramenta gratuita para teste de APIs, quando é feita a requisição para a rota /main/protect
sem que sejam passadas as informações de usuário e senha. O retorno é um status HTTP 403, que informa que o usuário não está autorizado a acessar o recurso.
O mesmo resultado é obtido para a rota /main/free
sem autenticação
Para obter um resultado de sucesso na requisição é necessário configurar a autenticação, conforme mostrado a seguir.
Esta configuração pode ser interessante para ambientes de desenvolvimento, mas dificilmente será utilizada em produção, a não ser em casos específicos em que apenas um usuário é necessário.
Personalizando configurações da autenticação Basic
Para personalizar alguns aspectos da autenticação Basic é preciso criar uma nova classe para redefinir as configurações do Spring Security. Esta classe sobrescreverá as configurações realizadas pela classe WebSecurityConfigurerAdapter
e seu código inicial é o seguinte
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
}
Conforme já mencionado, esta é uma classe de configuração para o Spring. Sendo assim, ela poderia ser explicitamente anotada com
@Configuration
. No entanto, como a anotação@EnableWebSecurity
já traz consigo a anotação@Configuration
não é necessária a repetição da mesma. Entretanto, não é errado fazer isso e o código fica mais legível.
Métodos de configuração
A classe WebSecurityConfigurerAdapter
possui alguns métodos de configuração com a assinatura configure
. Estes métodos podem ser sobrescritos para a personalização da autenticação com relação às requisições HTTP e também dos usuário permitidos.
Método configure(HttpSecurity http)
Este método permite a alteração de configurações relativas às requisições do protocolo HTTP, tais como o fluxo de autenticação, o formulário de login padrão (já citado anteriormente), as requisições que serão protegidas pela autenticação, o tipo de token que será utilizado (quando necessário), configuração de servidores stateless ou stateless, dentre outras configurações. A documentação oficial do Spring traz uma relação das configurações possíveis de serem realizadas neste método de configuração.
Para este projeto serão utilizadas as seguintes configurações
- Definição do HTTP Basic como método de autenticação
- Desabilitação do form login
- Definição de rotas que deverão ser autenticadas ou não
- Configuração de gerenciamento de sessão
Os dois primeiros itens da lista são configurados da seguinte forma
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
}
O form login é habilitado através do método formLogin()
. A omissão deste método na configuração é suficiente para a sua inativação. Para concatenar configurações pode ser utilizado o método and()
. Sendo assim, a habilitação do login pode ser feita com a configuração http.httpBasic().and.formLogin()
.
A definição de quais rotas deverão ser autenticadas ou não é feita pelo método authorizeRequests()
. Este método permite a configuração através dos métodos antMatchers
e anyRequest
, sendo o primeiro para definir de forma personalizada a rota e o segundo uma forma generalista para buscar todas as outras requisições. Neste exemplo será configurada a permissão para acessar a rota /main/free
sem autenticação e todas as outras rotas precisarão passar por autenticação prévia.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.authorizeRequests()
.antMatchers("/main/free").permitAll()
.anyRequest().authenticated();
}
Outra configuração importante é referente ao controle de sessão e armazenamento de cookies. Por padrão, o Spring Security armazena cookies que retém informações sobre a autenticação previamente realizada. Isso permite que após uma requisição bem sucedida com autenticação o usuário consiga acessar o recurso mesmo que não utilize os dados de autenticação. Esse é um problema que deve ser resolvido e uma das formas de fazer isso é configurando o gerenciamento de sessão para que seja utilizada uma política stateless, ou seja, sem armazenamento de estado. Para isso, pode ser adicionado à configuração anterior o método sessionManagement
, da seguinte forma.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/main/free").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Método configure(AuthenticationManagerBuilder auth)
Este método permite a configuração de usuários e senhas para a aplicação. Neste artigo é abordada apenas uma estratégia de armazenamento destes usuários em memória de forma completamente programática (definidos no próprio código).
Para configurar a autenticação em memória é utilizado o método inMemoryAuthentication()
que permite as seguintes configurações
- Nome do usuário:
withUser("nome")
- Senha:
password("password")
- Permissões:
roles("roles")
A partir da versão 5 do Spring Security é necessário colocar qualquer tipo de senha de forma codificada para o correto funcionamento. Uma forma de fazer isso é colocar a configuração do password como password("{noop}password")
, o que delega ao NoOpPasswrodEncoder
a responsabilidade de realizar a codificação. Essa opção deve ser utilizada com muito cuidado, pois expõe um dado sensível no código, e não deve ser utilizada em ambiente de produção.
A configuração completa do método fica da seguinte forma
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("alexandre")
.password("{noop}123456")
.roles("roles");
}
É possível colocar outros usuários nesta configuração utilizando o conectivo and()
.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("alexandre")
.password("{noop}123456")
.roles("roles")
.and()
.withUser("admin")
.password("{noop}admin")
.roles("roles");
}
Conclusão
Este artigo mostrou a configuração inicial de autenticação Basic utilizando o Spring Security. Foram abordadas as questões sobre os métodos necessários para uma personalização simples da autenticação como configuração de usuários e senhas e definição de rotas que devem ou não ser autenticadas.
Apesar de haver uma configuração obrigatória de definição de permissões na configuração de usuários, a mesma não foi utilizada para definição de autorizações nas rotas. Esse tema poderá ser explicado em um futuro trabalho.
Posted on March 11, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.