O Spring Security é uma ferramenta poderosa para garantir a segurança de suas aplicações Java, especialmente em APIs REST. Ele fornece uma série de recursos para autenticação, autorização e proteção contra ameaças comuns. Neste post, vamos abordar passo a passo como configurar o Spring Security em um projeto Java para uma API REST.
O que é o Spring Security?
O Spring Security é um módulo do Spring Framework que oferece suporte à segurança em nível de método, classe e até mesmo em URLs. Ele fornece uma infraestrutura abrangente para autenticação e autorização, permitindo que os desenvolvedores controlem o acesso aos recursos de suas aplicações.
Adicionando o Spring Security ao Projeto
Após adicionar o Spring Security ao seu projeto, você notará que as rotas agora requerem autenticação. Uma senha de acesso será gerada no terminal para garantir a segurança das suas APIs.
Stateful vs Stateless
Por padrão, o Spring Security pode ser configurado como Stateful ou Stateless. A diferença principal está no armazenamento do estado da sessão. Stateful mantém o estado do usuário no servidor, enquanto Stateless não mantém nenhum estado, sendo mais escalável. Vamos optar por Stateless para este exemplo.
Configurando o Spring Security – Passo a Passo
1º – Criar Tabela de Usuários
Inicie criando a tabela responsável por gerenciar os usuários, com campos como e-mail e senha.
CREATE TABLE usuarios ( id INT PRIMARY KEY AUTO_INCREMENT, login VARCHAR(50) NOT NULL, senha VARCHAR(100) NOT NULL );
2º – Repositories e Configuração do Spring Security
Crie os repositories para acessar a tabela de usuários. Em seguida, configure uma classe que implemente a interface UserDetailsService
, responsável por informar ao Spring Security como carregar e realizar o login.
@Service
public class AutenticacaoService implements UserDetailsService {
@Autowired
private UsuarioRepository usuarioRepository;
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Usuario usuario = usuarioRepository.findByLogin(username).orElseThrow(() -> new UsernameNotFoundException("Usuário não encontrado"));
return new User(usuario.getLogin(), usuario.getSenha(), Collections.emptyList());
}
}
3º – Configurando Stateless
Crie uma classe de configuração para o Spring Security e configure-o para ser Stateless.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AutenticacaoService autenticacaoService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(autenticacaoService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
4º – Configurando o AuthenticationManager e o Controller de Login
Configure o AuthenticationManager
e crie um Controller para realizar o login.
@Configuration
public class AuthenticationConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private AutenticacaoService autenticacaoService;
@Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder builder) throws Exception {
return builder.userDetailsService(autenticacaoService).passwordEncoder(passwordEncoder()).build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenService tokenService;
@PostMapping
public ResponseEntity<String> login(@RequestBody LoginDTO dto) {
Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(dto.getLogin(), dto.getSenha()) );
String token = tokenService.gerarToken(authentication);
return ResponseEntity.ok(token);
}
}
5º – Configurando a Senha dos Usuários
Configure como as senhas dos usuários são salvas, o algoritmo utilizado e prepare a entidade de usuário.
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public class Usuario implements UserDetails {
// Métodos da interface UserDetails // ...
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override public String getPassword() {
return this.senha;
}
@Override public String getUsername() {
return this.login;
}
}
6º – Adicionando a Lib do JWT
Adicione a dependência do JWT no Maven.
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency>
7º – Configurando a Geração de Token
Crie uma classe para gerar tokens JWT e integre-a ao Controller de Login.
public class TokenService {
private final String chaveSegredo = "chave-secreta";
public String gerarToken(Authentication authentication) {
Usuario usuario = (Usuario) authentication.getPrincipal();
Date hoje = new Date();
// Token expira em 1 hora
Date dataExpiracao = new Date(hoje.getTime() + 3600000);
return Jwts.builder()
.setIssuer("API de Autenticação")
.setSubject(usuario.getId().toString())
.setIssuedAt(hoje)
.setExpiration(dataExpiracao)
.signWith(SignatureAlgorithm.HS256, chaveSegredo)
.compact();
}
}
Conclusão
Esses passos devem ajudar na configuração do Spring Security em uma API REST Java, proporcionando uma camada robusta de segurança para suas aplicações. Lembre-se de ajustar os códigos conforme as necessidades específicas do seu projeto.