Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

11
respostas

Erro 400 bad request

Olá estou tendo o mesmo problema que alguns alunos relataram aqui, erro 400 na chamada do /auth, alguém sabe o que pode ser ? Até 5 minutos atrás tudo estava funcionando, der repente parou.

11 respostas

Oi Alexandre,

Posta aqui como você disparou a requisção no postman e as suas classes controller, dto e securityConfigurations.

Olá, segue a SecurityConfigurations

package br.com.framework.api.frameworkapi.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import br.com.framework.api.frameworkapi.repository.UserRepository;

@EnableWebSecurity
@Configuration
public class SecurityConfigurations extends WebSecurityConfigurerAdapter {

    @Autowired
    private ServiceAuthentication serviceAuthentication;

    @Autowired
    private TokenService tokenService;

    @Autowired
    UserRepository userRepository;

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

    // Authentication Settings
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(serviceAuthentication).passwordEncoder(new BCryptPasswordEncoder());
    }

    // Authorization settings
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/auth").permitAll()
        .anyRequest()                
        .authenticated()
        .and().csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().addFilterBefore(new AuthenticatorTokenFilter(tokenService, userRepository), UsernamePasswordAuthenticationFilter.class);
        }

    // Static resource settings (js, css, images)
    @Override
    public void configure(WebSecurity web) throws Exception {

    }

    /*public static void main(String[] args) {
        String senha = new BCryptPasswordEncoder().encode("12345");
        System.out.println(senha);
    }*/

}

Segue o AuthController

package br.com.framework.api.frameworkapi.controller;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import br.com.framework.api.frameworkapi.dto.TokenDto;
import br.com.framework.api.frameworkapi.form.AuthForm;
import br.com.framework.api.frameworkapi.security.TokenService;

@RestController
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RequestMapping("/auth")
public class AuthController {

    @Autowired
    private AuthenticationManager authManager;

    @Autowired
    private TokenService tokenService;

    @PostMapping
    public ResponseEntity<TokenDto> authetic(@RequestBody @Valid AuthForm form){
        UsernamePasswordAuthenticationToken data = form.convert();

        try {
            Authentication authentication = authManager.authenticate(data);
            String token = tokenService.generateToken(authentication);
            return ResponseEntity.ok(new TokenDto(token, "Bearer"));
        } catch (org.springframework.security.core.AuthenticationException e) {
            System.out.println("dando ruim aqui");
            return ResponseEntity.badRequest().build();
        }

    }

}

TokenDto

package br.com.framework.api.frameworkapi.dto;

public class TokenDto {

    private String token;
    private String type;

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

    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

}

TokenService

package br.com.framework.api.frameworkapi.security;

import java.util.Date;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import br.com.framework.api.frameworkapi.model.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Service
public class TokenService {

    @Value("${framework-api.jwt.expiration}")
    private String expiration;

    @Value("${framework-api.jwt.secret}")
    private String secret;

    public String generateToken(Authentication authentication) {
        User logged = (User) authentication.getPrincipal();
        Date now = new Date();
        Date dateExpiration = new Date(now.getTime() + Long.parseLong(expiration));
        return Jwts.builder().setIssuer("Framework API").setSubject(logged.getId().toString()).setIssuedAt(now)
                .setExpiration(dateExpiration).signWith(SignatureAlgorithm.HS256, secret).compact();
    }

    public boolean isValidToken(String token) {
        try {
            Jwts.parser().setSigningKey(this.secret).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public Long getIdUser(String token) {
        Claims claims = Jwts.parser().setSigningKey(this.secret).parseClaimsJws(token).getBody();
        return Long.parseLong(claims.getSubject());
    }

}

AuthenticatorTokenFilter

package br.com.framework.api.frameworkapi.security;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import br.com.framework.api.frameworkapi.model.User;
import br.com.framework.api.frameworkapi.repository.UserRepository;

public class AuthenticatorTokenFilter extends OncePerRequestFilter {

    private TokenService tokenService;
    private UserRepository userRepository;

    public AuthenticatorTokenFilter(TokenService tokenService, UserRepository userRepository) {
        this.tokenService = tokenService;
        this.userRepository = userRepository;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String token = recoverToken(request);
        boolean valid = tokenService.isValidToken(token);
        if (valid) {
            authenticationClient(token);
        }

        filterChain.doFilter(request, response);

    }

    private void authenticationClient(String token) {
        Long idUser = tokenService.getIdUser(token);
        User user = userRepository.findById(idUser).get();
        UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);

    }

    private String recoverToken(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token == null || token.isEmpty() || !token.startsWith("Bearer ")) {
            return null;
        }
        return token.substring(7, token.length());
    }

}

ServiceAuthentication

package br.com.framework.api.frameworkapi.security;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import br.com.framework.api.frameworkapi.model.User;
import br.com.framework.api.frameworkapi.repository.UserRepository;

@Service
public class ServiceAuthentication implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> user = userRepository.findByUsername(username);
        if (user.isPresent()) {
            return user.get();
        }

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

}

Segue como fiz a requisição no postman 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

Segue o retorno que aparece no console do eclipse

Hibernate: 
    select
        user0_.id as id1_7_,
        user0_.pwd as pwd2_7_,
        user0_.username as username3_7_ 
    from
        users user0_ 
    where
        user0_.username=?
dando ruim aqui

A principio nada de problemas nos códigos que você mandou. E a requsição está chegando normalmente, pois o select foi efetuado.

Coloca essa linha no seu catch, do AuthController:

} catch (org.springframework.security.core.AuthenticationException e) {
    e.printStackTrace();

    System.out.println("dando ruim aqui");
    return ResponseEntity.badRequest().build();
}

E posta aqui a exception que vai sair no console.

Segue o resultado, ficou mais simples o entendimento agora, faltou um construtor padrão na entity User, eu havia criado apenas com os campos necessários


org.springframework.security.authentication.InternalAuthenticationServiceException: No default constructor for entity:  : br.com.framework.api.frameworkapi.model.User; nested exception is org.hibernate.InstantiationException: No default constructor for entity:  : br.com.framework.api.frameworkapi.model.User

Correção

public User () {

    }