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.
Top comments (0)