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

Erro nos outros endpoints apos autenticação

Eu queria na hora de fazer a autenticação que além do token e tipo de token me retornasse o nome do usuário e perfil(no meu caso se chama nível)

Na AutenticacaoController fiz o seguinte: (Que funciona na hora do login)

    Long nivelID = (long) 0;
    String nome = null;

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

        try {

            Authentication authentication = authManager.authenticate(dadosLogin);
            String token = tokenService.gerarToken(authentication);    

            buscaUsuario(dadosLogin.getPrincipal().toString());    

            return ResponseEntity.ok(new TokenDto(token, "Bearer", nome, nivelID ));

        } catch (AuthenticationException e) {
            System.out.println("Erro AuthenticationException - classe AutenticacaoController");
            return ResponseEntity.badRequest().build();
        }

    }

    @GetMapping
    public void buscaUsuario(String email) {

        List<LoginCustom2> result = lRepository.findByEmail(email);            
        for (LoginCustom2 l : result) {
            nome = l.getNome();
            nivelID = l.getNivel().getId();
        }        
    }

Mas começou a da erro nas outras requisições, porque toda requisição que faço passa por ali

Erro:

java.lang.NumberFormatException: For input string: "email@email"
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) ~[na:na]
    at java.base/java.lang.Long.parseLong(Long.java:711) ~[na:na]
    at java.base/java.lang.Long.parseLong(Long.java:836) ~[na:na]
    at br.com.example.config.security.TokenService.getIdUser(TokenService.java:50) ~[classes/:na]
    at br.com.example.config.security.AutenticacaoViaTokenFilter.autenticarUsuario(AutenticacaoViaTokenFilter.java:50) ~[classes/:na]
    at br.com.example.config.security.AutenticacaoViaTokenFilter.doFilterInternal(AutenticacaoViaTokenFilter.java:42) ~[classes/:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.5.3.jar:5.5.3]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.5.3.jar:5.5.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-5.3.12.jar:5.3.12]

Tem algum jeito melhor que posso fazer isso??

13 respostas

Oi Gabriela,

Parece que o problema é na hora de gerar o token. Posta aqui a sua classe TokenService

Não mudei nada nela, está como vi no curso

@Service
public class TokenService {

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

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

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

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

    public boolean isTokenValido(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());
    }

}

Antes de eu colocar pra controller me trazer nome e nível estava funcionando normal, creio que o erro seja na controller de autenticação mesmo

Entendi, mas a exception está sendo lançada na classe AutenticacaoViaTokenFilter. Posta ela aqui também.

public class AutenticacaoViaTokenFilter extends OncePerRequestFilter {

    private TokenService tokenService;
    private UsuarioRepository userRepository;

    public AutenticacaoViaTokenFilter(
            TokenService tokenService, 
            UsuarioRepository userRepository) {
        this.tokenService = tokenService;
        this.userRepository = userRepository;
    }

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

        String token = recuperarToken(request);

        // Verifica se o token gerado é valido
        boolean isTokenValid = tokenService.isTokenValido(token);

        if (isTokenValid) {
            autenticarUsuario(token);
        }

        filterChain.doFilter(request, response);

    }

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

    private String recuperarToken(HttpServletRequest request) {

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

}

Quando gera o token tem essa linha na classe TokenService:

.setSubject(logado.getId().toString())

Mas parece que no seu caso não está setando no subject o id do usuário, mas sim o email. E com isso dá erro nessa linha da classe AutenticacaoViaTokenFilter:

Long idUser = tokenService.getIdUser(token);

Porque não vem um Long e sim uma String.

Mas meu ID é Long mesmo

@Entity
@Table(name = "tbl_login")
public class Login implements UserDetails{

    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "login_id")
    private Long id;

    @Column(name = "login")
    private String email;
    private String senha;

Voce consegue compartilhar o seu projeto? Se tiver no github seria o ideal

Professor, desculpa a demora, mas de alguma forma funcionou, não sei o que fiz mas parou de dá esse erro rsrs

mas agora apareceu outro referente a isso. Na hora do PUT do login começou a aparecer um erro de Lazy, aparentemente minha entidade nível está com atraso e ai sempre que vou alterar um dado da esse erro, no banco a info é alterada sem problema mas acaba me retornando esse erro(500) apenas na primeira vez e na segunda vez me retorna 200

2021-12-09 08:15:31.999 ERROR 10512 --- [nio-8082-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: br.com.example.controller.dto.custom.LoginAddDto["nivel"]->br.com.example.model.custom.NivelAdd$HibernateProxy$DbWQLM2q["hibernateLazyInitializer"])] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: br.com.example.controller.dto.custom.LoginAddDto["nivel"]->br.com.example.model.custom.NivelAdd$HibernateProxy$DbWQLM2q["hibernateLazyInitializer"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1514) ~[jackson-databind-2.12.5.jar:2.12.5]
    at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1006) ~[jackson-databind-2.12.5.jar:2.12.5]

Nivel

@Entity
@Table(name = "tbl_nivel_acesso")
public class NivelAdd {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "nivel_id")
    private Long id;

    @Column(name = "nome_nivel")
    private String nome;

    @Column(name = "data_criacao")
    private LocalDateTime dataCriacao = LocalDateTime.now();

    @Column(name = "data_ultima_alteracao")
    private LocalDateTime dataUltimaAlteracao = LocalDateTime.now();
}

Oi Gabriela,

Pode ser o jeito que foi implementando a funcionalidade PUT. Manda aqui o código do controller dessa funcionalidade.

    @PutMapping("/{id}")
    @Transactional
    public ResponseEntity<LoginAddDto> alteraLogin(@PathVariable Long id, 
            @RequestBody @Valid AlterLoginCustomForm form) {    
        System.out.println("\nid: "+id);
        Optional<LoginCustom> op = loginRepository.findById(id);
        if(op.isPresent()) {            
            LoginCustom s = form.atualizar(id, loginRepository,nRepository);            
            s.setSenha(config.criptografa(s.getSenha()));            
            return ResponseEntity.ok(new LoginAddDto(s));
        }
        return ResponseEntity.notFound().build();            
    }
solução!

Manda tambem suas classes AlterLoginCustomForm e LoginAddDto :D

Achei o erro prof, esqueci de setar a senha no atualizar() da classe AlterLoginCustomForm rsrs, desculpa o vacilo

Ah que bom que conseguiu resolver :D

Bons estudos!