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

[Dúvida] Login funcionando, mas outras requisições não, mesmo utilizando o token.

Estou com esse codigo compilando, mas dando erro 403 para as requisições e sim, estou utilizando o toke no corpo. No codigo finalizado do curso está sendo utilizado o "antMatchers", que não roda mais na versão que estou usando, substitui por "requestMatchers", compila, aceita login, mas não funciona o restante.

package med.voll.api.infra.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.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration @EnableWebSecurity public class SecurityConfigurations {

@Autowired
private SecurityFilter securityFilter;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().authorizeRequests()
            .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();
}

}

5 respostas

Oi Leonardo!

Sobre o antMatchers, tem uma explicação no curso: https://cursos.alura.com.br/course/spring-boot-aplique-boas-praticas-proteja-api-rest/task/119206

Sobre o erro 403, tem vários possíveis motivos para acontecer. Posta aqui o código completo das suas classes:

  1. TokenService
  2. SecurityFilter
  3. AutenticacaoController

Fala Rodrigo, beleza?

https://github.com/LeoMalavolta/arena_cross

1.TokenService:

package arena.cross.api.infra.security;

@Service public class TokenService {

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

public String gerarToken(Usuario usuario){
    try {
        var algoritmo = Algorithm.HMAC256(secret);
        return JWT.create()
                .withIssuer("API Arena.cross")
                .withSubject(usuario.getLogin())
                .withExpiresAt(dataExpiracao())
                .sign(algoritmo);
    } catch(JWTCreationException exception){
        throw new RuntimeException("Erro ao gerar token jwt", exception);
    }
}

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

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

}

2.SecurityFilter:

package arena.cross.api.infra.security;

import java.io.IOException;

@Component public class SecurityFilter extends OncePerRequestFilter {

@Autowired
private TokenService tokenService;

@Autowired
private UsuarioRepository usuarioRepository;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    var tokenJWT = recuperarToken(request);
    if (tokenJWT != null) {
        var subject = tokenService.getSubject(tokenJWT);
        var usuario = usuarioRepository.findByLogin(subject);

        var authentication = new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }


    filterChain.doFilter(request, response);
}


private String recuperarToken(HttpServletRequest request) {
    var authorizationHeader = request.getHeader("Authorization");
    if (authorizationHeader != null) {
        return authorizationHeader.replace("Bearer", "");
    }
    return null;
}

}

3.AutenticacaoController:

package arena.cross.api.controller;

import arena.cross.api.domain.usuario.DadosAutenticacao; import arena.cross.api.domain.usuario.Usuario;

@RestController @RequestMapping("/login") public class AutenticacaoController {

@Autowired
private AuthenticationManager manager;

@Autowired
private TokenService tokenService;

@PostMapping
public ResponseEntity efetuarLogin(@RequestBody @Valid DadosAutenticacao dados) {
    var authenticationToken = new UsernamePasswordAuthenticationToken(dados.login(), dados.senha());
    var authentication = manager.authenticate(authenticationToken);
    var tokenJWT = tokenService.gerarToken((Usuario) authentication.getPrincipal());
    return ResponseEntity.ok(new TokenDadosJWT(tokenJWT));

}

}

solução!

Oi Leonardo!

Acho que o problema está nessa linha:

return authorizationHeader.replace("Bearer", "");

Faltou o espaço em branco após a palavra Bearer:

return authorizationHeader.replace("Bearer ", "");

Fala Rodrigo!

Não sei o que é pior, quando é um grande erro ou um pequeno como esse kkkkk

Funcionou aqui, muito obrigado!

Ahh o meu era o mesmo problema.

Obrigada ><