ainda tomando erro 403, ja verifiquei o codigo e nao encontro o pq desse erro
E
ainda tomando erro 403, ja verifiquei o codigo e nao encontro o pq desse erro
E
tokenService
package med.voll.API.infra.security;
import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTCreationException; import com.auth0.jwt.exceptions.JWTVerificationException; import med.voll.API.domain.usuario.Usuario; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service;
import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset;
@Service public class TokenService {
@Value("${api.security.token.secret}")
private String secret;
public String gerarToken(Usuario usuario) {
System.out.println(secret);
try {
var algoritmo = Algorithm.HMAC256(secret);
return JWT.create()
.withIssuer("API Voll.med")
.withSubject(usuario.getLogin())
.withExpiresAt(dataExpiracao())
.sign(algoritmo);
} catch (JWTCreationException exception) {
throw new RuntimeException("erro ao gerrar token jwt", exception);
}
}
public String getSubjec(String tokenJWT) {
try {
var algoritmo = Algorithm.HMAC256(secret);
return JWT.require(algoritmo)
.withIssuer("API Voll.med")
.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"));
}
}
securityFilter
package med.voll.API.infra.security;
import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import med.voll.API.domain.usuario.UsuarioRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component//serve para que o spring rode um componente generico public class SecurityFilter extends OncePerRequestFilter {
@Autowired
private TokenService tokenService;
@Autowired
private UsuarioRepository repository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
var tokenJWT = recuperarToken(request);
if (tokenJWT != null) {
var subject = tokenService.getSubjec(tokenJWT);
var usuario = repository.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;
}
}
securityConfiguration
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.DefaultSecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity @Configuration//classe configuracoes de seguranca public class SecurityConfigurations {
@Autowired
private SecurityFilter securityFilter;
@Bean
public DefaultSecurityFilterChain 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();
}
}
@Bean public DefaultSecurityFilterChain SecurityFilterChain (HttpSecurity http) throws Exception
nessa parte acima o intellij me obrigou a colocar esse ( DefaultSecurityFilterChain )
Oi Thiago!
O problema está no seu método recuperarToken
da classe SecurityFilter
:
return authorizationHeader.replace("Bearer", "");
Faltou um espaço em branco depois da palavra Bearer:
return authorizationHeader.replace("Bearer ", "");
eu coloquei esse espaço e ainda to tomando esse erro
Coloca um system.out para ver no console o token que está chegando:
var tokenJWT = recuperarToken(request);
System.out.println("\n\n\n TOKEN QUE CHEGOU NA API: " +tokenJWT +"\n\n\n" );
Está aí o problema, não está chegando o token mesmo :D
Como chegou undefined, vou chutar que você está disparando a requisição por uma aplicação frontend, então o erro está no envio da requisição no código do frontend em si.
to usando o insomnia
manda um print aqui da requisição no insomnia.
Ah sim, é na requisição de login, que não tem token mesmo.
Geralmente dá 403 quando envia um login/senha que não está cadastrado no banco de dados. Coloca esse try catch no controller para verificar:
@PostMapping
public ResponseEntity efetuarLogin(@RequestBody @Valid DadosAutenticacao dados) {
try {
var authenticationToken = new UsernamePasswordAuthenticationToken(dados.login(), dados.senha());
var authentication = manager.authenticate(authenticationToken);
var tokenJWT = tokenService.gerarToken((Usuario) authentication.getPrincipal());
return ResponseEntity.ok(new DadosTokenJWT(tokenJWT));
} catch(Exception e) {
System.out.println("\n\n\n ERRO AO FAZER LOGIN: \n\n\n")
e.printStackTrace();
return ResponseEntity.badRequest().body("erro de autenticacao!");
}
}
A consulta devolveu null, então no seu banco de dados, na tabela de usuarios, não deve ter esse login que você está enviando: joao.carlos@voll.med ou a senha que você mandou está incorreta.
Faz um select na sua tabela de usuários para verificar.
você poderia bota o @valid como o primeiro parâmetro na assinatura da funçao ? public ResponseEntity efetuarLogin(@Valid @RequestBody DadosAutenticacao dados) {
entao, eu tava justamente testando outros logins pra ver se ia, mas todos dao erro
Ramon, coloquei como primeiro mas nada mudou
O problema é que você está testando com os emails da tabela de medicos, mas na verdade deveria ser da tabela de usuarios.
Na sua tabela de usuarios so tem 2 logins:
ana.albuquerque@med e paulo.albuquerque@med
eu utilizei os da tabela de usuarios tbm, mesmo erro
Parece que o problema é na senha.
Roda esse comando no seu banco de dados:
update usuarios set senha = '$2a$10$6USmofnjEc4AodqxRTrzTecI9ZCrrPuhGq0EaM0iu3iV3yp7WYnGa';
Feito