Olá a todos, eu estava tendo problemas na autenticação da minha API, a causa era o fato de que as senhas dos meus usuários no banco de dados não estavam criptografadas, por isso decidi implementar a funcionalidade de cadastro para salvar os usuários com senhas já codificadas. Consegui implementar essa funcionalidade e resolvi compartilhar o código aqui no fórum para ajudar quem estiver com dificuldades nessa parte.
Antes de tudo, inseri um registro na entidade Perfil, que representará usuários comuns, com o seguinte comando SQL:
INSERT INTO Perfil (nome) VALUES ('usuario');
É necessário também criar um método na classe usuário para adicionar um Perfil na lista de perfis:
public void adicionaPerfil(Perfil perfil) {
this.perfis.add(perfil);
}
Controller responsável por realizar os cadastros:
@RestController
@RequestMapping("/register")
public class CadastroController {
//Injetando os repositories
@Autowired
private UsuarioRepository usuarioRepository;
@Autowired
private PerfilRepository perfilRepository;
@PostMapping
@Transactional
public ResponseEntity<?> cadastrar(@RequestBody @Valid CadastroForm form) {
//Fazendo a validação
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<CadastroForm>> violations = validator.validate(form);
if (violations.isEmpty()) {
Usuario usuario = form.toUsuario();
//Como a chave primária da entidade Usuário é o id, o banco de dados permitirá que
//existam dois ou mais usuários com o mesmo email, por isso devemos fazer a verificação manualmente.
if (usuarioRepository.findByEmail(usuario.getEmail()).isPresent()) {
return ResponseEntity.badRequest().body("Este email já está cadastrado!");
}
//Por enquanto, estou definindo todos os usuários que se cadastram como usuários comuns
usuario.adicionaPerfil(this.perfilRepository.findByNome("usuario"));
//Codificando a senha, para salvar a senha já criptografada no banco de dados
String senha = new BCryptPasswordEncoder().encode(usuario.getSenha());
usuario.setSenha(senha);
usuarioRepository.save(usuario);
//O correto seria criar uma URI para detalhar um usuário, mas por enquanto vamos enviar null:
return ResponseEntity.created(null).body(new UsuarioDto(usuario.getId(), usuario.getNome(), usuario.getEmail()));
}
//Enviando 400 caso haja algum problema de validação
return ResponseEntity.badRequest().body(violations);
}
}
Classe PerfilRepository:
public interface PerfilRepository extends JpaRepository<Perfil, Long> {
Perfil findByNome(String nome);
}
Classe com o formulário de cadastro:
public class CadastroForm {
//Fazendo algumas validações
@NotEmpty @NotNull @Email
private String email;
@NotEmpty @NotNull @Size(min=3, max=20)
private String nome;
@NotEmpty @NotNull @Size(min=6, max=30)
private String senha;
// getters, setters e construtores
}
Classe UsuarioDto, para enviar no ResponseEntity.created():
public class UsuarioDto {
private Long id;
private String nome;
private String email;
// getters, setters e construtores
}
Por último, devemos tornar esse endpoint público, no método config da classe SecurityConfigurations:
.antMatchers(HttpMethod.POST, "/register").permitAll()
Isso é tudo, espero ter conseguido ajudar alguém!