Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

400 Bad Request - MongoDB para salvar usuarios

Olá, estou desenvolvendo uma aplicação e preciso usar o banco MongoDB com base no projeto das aulas iniciei apenas a entidade usuário para tentar gerar o token e salvar no banco. No banco está ok, salvou meu usuário, criou a tabela certinho. No meu controller de usuários criei 2 endpoints um para listar todos (GET) e outro para salvar (POST) porém no endpoint (POST)"/auth" recebo um 400 pelo Postman. Seguem minhas classes:

Usuário:

@Document(collection = "usuario")
public class Usuario implements UserDetails, Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY)
    private String id;
    private String nome;
    private String email;
    private String senha;

    @ManyToMany(fetch = FetchType.EAGER)
    private List<Perfil> perfis = new ArrayList<>();

    public Usuario(){

    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Usuario other = (Usuario) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.perfis;
    }

    @Override
    public String getPassword() {
        return this.senha;
    }

    @Override
    public String getUsername() {
        return this.email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

Controller de Usuário:

@RestController
@RequestMapping("API_SGS_TI/usuario")
public class UsuarioController {

    @Autowired
    private UsuarioRepository repository;


    @GetMapping("/listarTodos")
    public ResponseEntity<List<Usuario>> findAll(){
        return ResponseEntity.ok(repository.findAll());
    }


    @PostMapping("/salvar")
    public ResponseEntity<Usuario> insert(@RequestBody @Valid Usuario user){
        return ResponseEntity.status(HttpStatus.CREATED).body(repository.insert(user));
    }

}

Repository de Usuário:


@Repository
public interface UsuarioRepository extends MongoRepository<Usuario, String> {

    Optional<Usuario> findByEmail(String email);

}Insira aqui a descrição dessa imagem para ajudar na acessibilidade Insira aqui a descrição dessa imagem para ajudar na acessibilidade Insira aqui a descrição dessa imagem para ajudar na acessibilidade

5 respostas

Oi Graciele,

Posta aqui o codigo da suas classes controller, dto, securityconfigurations e service de autenticação.

Controllers:

@RestController
@RequestMapping("/auth")
public class AutenticacaoController {

    @Autowired
    private AuthenticationManager authManager;

    @Autowired
    private TokenService tokenService;

    @PostMapping
    public ResponseEntity<TokenDto> autenticar(@RequestBody @Valid LoginForm form) {
        UsernamePasswordAuthenticationToken dadosLogin = form.converter();

        try {
            Authentication authentication = authManager.authenticate(dadosLogin);
            String token = tokenService.gerarToken(authentication);
            return ResponseEntity.ok(new TokenDto(token, "Bearer"));
        } catch (AuthenticationException e) {
            return ResponseEntity.badRequest().build();
        }
    }

}

DTO:

public class TokenDto {

    private String token;
    private String tipo;

    public TokenDto(String token, String tipo) {
        this.token = token;
        this.tipo = tipo;
    }

    public String getToken() {
        return token;
    }

    public String getTipo() {
        return tipo;
    }

}

LoginForm:

public class LoginForm {

    private String email;
    private String senha;

    public String getEmail() {
        return email;
    }

    public String getSenha() {
        return senha;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public UsernamePasswordAuthenticationToken converter() {
        return new UsernamePasswordAuthenticationToken(email, senha);
    }

}

Security Configurations:

Autenticação

@Service
public class AutenticacaoService implements UserDetailsService {

    @Autowired
    private UsuarioRepository repository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Optional<Usuario> usuario = repository.findByEmail(email);
        if (usuario.isPresent()) {
            return usuario.get();
        }

        throw new UsernameNotFoundException("Dados inválidos!");
    }

}

Security

@EnableWebSecurity
@Configuration
public class SecurityConfigurations extends WebSecurityConfigurerAdapter {

    @Autowired
    private AutenticacaoService autenticacaoService;

    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    //Configuracoes de autenticacao
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(autenticacaoService).passwordEncoder(new BCryptPasswordEncoder());
    }

    //Configuracoes de autorizacao
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        .antMatchers(HttpMethod.GET, "/topicos").permitAll()
        .antMatchers(HttpMethod.GET, "/topicos/*").permitAll()
        .antMatchers(HttpMethod.POST, "/auth").permitAll()
                .antMatchers(HttpMethod.POST, "/API_SGS_TI/usuario/salvar").permitAll()
                .antMatchers(HttpMethod.GET, "/API_SGS_TI/usuario/listarTodos").permitAll()
        .anyRequest().authenticated()
        .and().csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }


    //Configuracoes de recursos estaticos(js, css, imagens, etc.)
    @Override
    public void configure(WebSecurity web) throws Exception {
    }

}

TokenService

@Service
public class TokenService {

    @Value("${forum.jwt.expiration}")
    private String expiration;

    @Value("${forum.jwt.secret}")
    private String secret;

    public String gerarToken(Authentication authentication) {
        Usuario logado = (Usuario) authentication.getPrincipal();
        Date hoje = new Date();
        Date dataExpiracao = new Date(hoje.getTime() + Long.parseLong(expiration));

        return Jwts.builder()
                .setIssuer("API do Fórum da Alura")
                .setSubject(logado.getId().toString())
                .setIssuedAt(hoje)
                .setExpiration(dataExpiracao)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

}

Na sua classe controller tem esse try/catch:

try {
    Authentication authentication = authManager.authenticate(dadosLogin);
    String token = tokenService.gerarToken(authentication);
    return ResponseEntity.ok(new TokenDto(token, "Bearer"));
} catch (AuthenticationException e) {
    return ResponseEntity.badRequest().build();
}

Coloca no catch um e.printStracktrace() para ver o que ta saindo de erro no console:

} catch (AuthenticationException e) {
    e.printStacktrace();
    return ResponseEntity.badRequest().build();
}

Boa tarde, sai a msg:

org.springframework.security.authentication.InternalAuthenticationServiceException: Query { "$java" : Query: { "email" : "backend@gmail.com" }, Fields: { }, Sort: { } } returned non unique result.

Os meus dois usuarios tem o mesmo e-mail.

solução!

Ah sim, então está aí o problema. Não pode ter mais de um usuário com o mesmo email, que é o campo de login no sistema.