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

500 Internal Server Error

Boa tarde! Quando vou realizar testes no postman no endpoint /api/auth, o postman devolve um 500 Internal Server Error!

E no console, recebo a seguinte Exception:

2021-10-31 17:17:42.368 ERROR 11692 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: class br.com.develfoodspringweb.develfoodspringweb.models.User cannot be cast to class br.com.develfoodspringweb.develfoodspringweb.models.Restaurant (br.com.develfoodspringweb.develfoodspringweb.models.User and br.com.develfoodspringweb.develfoodspringweb.models.Restaurant are in unnamed module of loader 'app')] with root cause

java.lang.ClassCastException: class br.com.develfoodspringweb.develfoodspringweb.models.User cannot be cast to class br.com.develfoodspringweb.develfoodspringweb.models.Restaurant (br.com.develfoodspringweb.develfoodspringweb.models.User and br.com.develfoodspringweb.develfoodspringweb.models.Restaurant are in unnamed module of loader 'app')

classe user

@Data
@Entity
@Table(name = "users")
@NoArgsConstructor
public class User implements UserDetails {

        //atributos


    @OneToMany(mappedBy = "user")
    private List<UserRequest> userRequest;

    public User(String name, String cpf, String login, String password, String email, String address, String phone) {
        this.name = name;
        this.cpf = cpf;
        this.login = login;
        this.password = password;
        this.email = email;
        this.address = address;
        this.phone = phone;
    }


    public User(UserForm userForm){
        this.name = userForm.getName();
        this.cpf = userForm.getCpf();
        this.login = userForm.getLogin();
        this.email = userForm.getEmail();
        this.address = userForm.getAddress();
        this.phone = userForm.getPhone();
    }

    @ManyToMany
    private List<Profile> userProfile = new ArrayList<>();

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

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

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

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

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

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

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

Classe Restaurant

@Entity
@Table(name = "restaurants")
@Data
@NoArgsConstructor
public class Restaurant implements UserDetails {

        //atributos

    @OneToMany(mappedBy = "restaurant")
    private List<Plate> plate;


    public Restaurant(String name, String cnpj, String login, String password, String email, String address, String phone) {
        this.name = name;
        this.cnpj = cnpj;
        this.login = login;
        this.password = password;
        this.email = email;
        this.address = address;
        this.phone = phone;
    }

    public Restaurant(RestaurantForm restaurantForm) {
        this.name = restaurantForm.getName();
        this.cnpj = restaurantForm.getCnpj();
        this.login = restaurantForm.getLogin();
        this.email = restaurantForm.getEmail();
        this.address = restaurantForm.getAddress();
        this.phone = restaurantForm.getPhone();
    }

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

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

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

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

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

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

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

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


3 respostas

Classe TOKENSERVICE

package br.com.develfoodspringweb.develfoodspringweb.security;

import br.com.develfoodspringweb.develfoodspringweb.models.Restaurant;
import br.com.develfoodspringweb.develfoodspringweb.models.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class TokenServ {

    //////////////////////////////////////////VALORES DO APPLICATION PROPERTIES/////////////////////////////////////////
    @Value("${develfoodspringweb.jwt.secret}")
    private String secret;

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


    public String generateToken(Authentication authentication) { //nessa classe vai a API para fazer a CRIAÇÃO DO TOKEN

        User logged = (User) authentication.getPrincipal();
        Restaurant restaurantLogged = (Restaurant) authentication.getPrincipal();
        Date today = new Date();
        Date expirationDate = new Date(today.getTime() + Long.parseLong(expiration));

        if (logged.equals(logged)) {
            return Jwts.builder()
                    .setIssuer("API da Develfood")
                    .setSubject(logged.getId().toString())
                    .setIssuedAt(today)
                    .setExpiration(expirationDate)
                    .signWith(SignatureAlgorithm.HS256, secret)
                    .compact();
        } else {
            return Jwts.builder()
                    .setIssuer("API da Develfood")
                    .setSubject(restaurantLogged.getId().toString())
                    .setIssuedAt(today)
                    .setExpiration(expirationDate)
                    .signWith(SignatureAlgorithm.HS256, secret)
                    .compact();
        }
    }

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

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

solução!

Oi Luis,

O problema é que você está com duas classes implementando a interface UserDetails no seu projeto, mas na classe TokenServ o login não pode ser realizado simultaneamente por um usuário e um restaurante.

Altere esse trecho de código:

public String generateToken(Authentication authentication) {
    User logged = (User) authentication.getPrincipal();
    Restaurant restaurantLogged = (Restaurant) authentication.getPrincipal();

Para:

public String generateToken(Authentication authentication) {
    Long loggedId = null;
    if (authentication.getPrincipal() instanceof User) {
        loggedId = ((User) authentication).getId();
    } else {
        loggedId = ((Restaurant) authentication).getId();
    }

    Date today = new Date();
    Date expirationDate = new Date(today.getTime() + Long.parseLong(expiration));
    return Jwts.builder()
            .setIssuer("API da Develfood")
            .setSubject(loggedId.toString())
            .setIssuedAt(today)
            .setExpiration(expirationDate)
            .signWith(SignatureAlgorithm.HS256, secret)
            .compact();

Daria para criar uma nova interface, contendo um metodo getId(), e colocar ambas as classes para implementá-la, para evitar esses if/else na classe tokenServ.

Bons estudos!

Opa, bom dia Professor!

Testei aqui sua alteração e funcionou!! Muito obrigado pela ajuda!!!

Tenha uma ótima semana.