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

Erro por estouro de vetor

Por algum motivo, quando eu tento logar um usuário já cadastrado no banco de dados retorna:

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

o código de login é :

@Component public class PerformLoginUseCase {

@Autowired
private AuthenticationManager manager;
@Autowired
TokenService tokenService;

public TokenJwtDto performLogin(UserLoginDTO data) {
    var authenticationToken = new UsernamePasswordAuthenticationToken(data.login(), data.password());

    //está chamando authenticateService
    Authentication authentication = manager.authenticate(authenticationToken);
    User userAuthenticated = (User) authentication.getPrincipal();

    String tokenJwt = tokenService.generateJwtToken(userAuthenticated);

    return new TokenJwtDto(tokenJwt);
}

}

@Service public class AuthenticateService implements UserDetailsService { @Autowired private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    return userRepository.findByLogin(username);
}

}

Usando system.out para acompanhar, percebi que ele estoura exatamente na chamada do método findByLogin, mas não sei por que:

public interface UserRepository extends JpaRepository<User, Long> { UserDetails findByLogin(String login);

@Query("""
        SELECT u FROM User u WHERE u.login = :login
        """)
User findByLoginToHandle(String login);

boolean existsByLogin(String login);

}

9 respostas

Oi!

Manda a stack trace da exception aqui.

segue: WARN 16904 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.security.authentication.InternalAuthenticationServiceException: Index 53 out of bounds for length 6]Insira aqui a descrição dessa imagem para ajudar na acessibilidade

eu ainda tentei mudar no banco de dados o tamanho da password e do login, mas não adiantou.

segue também uma sequência de System.out, mostrando que estoura na consulta de findByLogin

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 acessibilidadeInsira aqui a descrição dessa imagem para ajudar na acessibilidade

aqui o registro que o login userandre@email.com existe no banco de dados: Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Estranho esse erro.

Manda aqui as suas classes: User, UserRepository e a SecurityConfigurations

User - >

package jr.acens.api.domain.user;

import jakarta.persistence.*;
import jakarta.validation.constraints.Pattern;
import jr.acens.api.domain.user.DTO.UserDTO;
import jr.acens.api.domain.user.DTO.UserForgotDTO;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

@Table(name = "users")
@Entity(name = "User")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    private String login;
    private String password;

    @Column(name = "token_email")
    private String tokenEmail;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "token_expiration")
    private LocalDateTime tokenExpiration;
    private UserRole role;
    @Pattern(regexp = "\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}", message = "O CPF deve seguir o formato 999.999.999-99")
    private String cpf;


    public User (UserDTO data) {
        this.login = data.login();
        this.password = data.password();
        this.role = UserRole.USER;
        this.name = data.name();
        this.cpf = data.cpf();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (this.role == UserRole.ADMIN) {
            return List.of(new SimpleGrantedAuthority("ROLE_ADMIN"),new SimpleGrantedAuthority("ROLE_USER"));
        }
        return List.of(new SimpleGrantedAuthority("ROLE_USER"));
    }

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

    @Override
    public String getUsername() {
        return login;
    }

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

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

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

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


    public void setPassword(String encodedPassword) {
        this.password = encodedPassword;
    }


    public void forgotPassword(UserForgotDTO data) {
        this.tokenEmail = data.tokenEmail();
        this.tokenExpiration = data.tokenExpiration();
    }

    public void setTokenEmail(String tokenEmail) {
        this.tokenEmail = tokenEmail;
    }
}

Repository

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

Security Configurations

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

Estranho, não vi nada de errado que pudesse causar esse erro.

Coloca um try catch no AuthenticateService para imprimir a stacktrace:

try {
    return userRepository.findByLogin(username);
} catch (Exception e) {
    e.printStackTrace();
    return null;
}

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

2023-09-27T16:24:43.492-03:00 WARN 16840 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation]

Insira aqui a descrição dessa imagem para ajudar na acessibilidadenão entendo como ele pode ter retornado null, se é um método padrão de findByLogin gerenciado pelo proprio jpa e existe o user com o login pretendido

O null foi conta do catch que coloquei return null para compilar.

Agora com stack trace ficou melhor de entender. É um erro relacionado com algum ENUM. Vou chutar que seria o atributo UserRole da sua classe Usuario, que deve ser um enum e não uma classe.

Como que esse atributo está sendo salvo na tabela do banco de dados? Manda um print aqui da tabela de usuário. No print que você mandou antes está cortado e apareceu apenas algumas colunas.

ele salva role 1 (user - padrão) ou 2 (admin - ainda nem criei)

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

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

o user possui um role padrão no construtor

public User (UserDTO data) { this.login = data.login(); this.password = data.password(); this.role = UserRole.USER; this.name = data.name(); this.cpf = data.cpf(); }

solução!

Entendi.

É melhor salvar como String ao invés de um int.

Adiciona essa anotação no atributo role da classe User:

@Enumerated(EnumType.STRING)
private UserRole role;

E altera essa coluna na tabela para salvar o nome da constante:

update users set role = 'USER' where id = 13;