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

[ERRO] Token não enviado no cabeçalho Authorization

Depois de configurar a classe

@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Autowired
    private TokenService tokenService;


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

        tokenService.getSubject(retrieveToken(request));

        filterChain.doFilter(request, response);

    }

    private String retrieveToken(HttpServletRequest request) {
        var authHeader = request.getHeader("Authorization");
        if(authHeader == null){
            throw new RuntimeException("Token não enviado no cabeçalho Authorization");
        }

        return authHeader.replace("Bearer ", "");
    }
}

não consigo logar pelo insomnia

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

seguem as classes:

SecurityConfiguration

@Configuration
@EnableWebSecurity
public class SecurityConfiguration implements WebMvcConfigurer {

    @Autowired
    private SecurityFilter securityFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        return http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeHttpRequests()
                .requestMatchers(HttpMethod.POST, "/login").permitAll()
                .anyRequest().authenticated()
                .and().addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception{
        return configuration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

TokenService

@Service
public class TokenService {

    @Value("{api.security.token.secret}")
    private String secret;

    public String tokenGenerator(Users users){
        try {
            var algorithm = Algorithm.HMAC256(secret);
            return  JWT.create()
                    .withIssuer("API Sica.School")
                    .withSubject(users.getLogin())
                    .withClaim("registration", users.getRegistration())
                    .withClaim("username", users.getUsername())
                    //.withExpiresAt(expirationData())
                    .sign(algorithm);
        } catch (JWTCreationException exception){
            // Invalid Signing configuration / Couldn't convert Claims.
            throw new RuntimeException("Erro ao gerar o token", exception);
        }
    }

    public String getSubject(String tokenJWT){
        try {
            var algorithm = Algorithm.HMAC256(secret);
            return JWT.require(algorithm)
                    .withIssuer("API Sica.School")
                    .build()
                    .verify(tokenJWT)
                    .getSubject();
        } catch (JWTVerificationException exception) {
            throw new RuntimeException("Token JWT inválido ou expirado!");
        }
    }

    private Instant expirationData() {
        return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-3:00"));
    }

}

uma curiosidade, parece que a classe SecurityConfiguration não está sendo carregada Insira aqui a descrição dessa imagem para ajudar na acessibilidade

3 respostas

Oi!

Faltou no seu filter o if para verificar se o token está vindo no cabeçalho da requisição, pois a requisição de login não envia token e com isso não deve chamar a classe tokenservice.

solução!

entendi, outra dúvida

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        return http.csrf(csrf -> csrf.disable())
                .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(ahr -> ahr.requestMatchers(HttpMethod.POST, "/login").permitAll())
                .authorizeHttpRequests(ahr -> ahr.requestMatchers(HttpMethod.POST, "/login/create/user").permitAll())
                .authorizeHttpRequests(ahr -> ahr.requestMatchers(HttpMethod.GET, "/teacher/created/{id}").permitAll())
                .authorizeHttpRequests(ahr -> ahr.anyRequest().authenticated())
                .build();
    }

eu preciso mapear ai todas as requisições para todos os meus endpoints ? e detalhe só consigo enviar as requições passando o token no insomnia

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

Oi Bruno! Tudo bem? Você só precisará mapear no SecurityFilterChain as requisições que deseja permitir livre acesso. As demais requisições por padrão já estarão mapeadas para que só sejam acessadas através de autenticação, devido ao seguinte trecho que você definiu:

.authorizeHttpRequests(ahr -> ahr.anyRequest().authenticated())

Caso desejasse, por exemplo, permitir que todas as requisições fossem de livre acesso para paths iniciados com /login, você poderia fazer algo como:

/login/**

Logo, estaria dando livre acesso a, como no seu exemplo, os seguintes endpoints:

/login

/login/create/user

Mas cuidado, pois todos os demais endpoints com este prefixo /login também estariam livres.