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

[Dúvida] Erro 403 em /login

Boa tarde! Após realizar todos os procedimentos, continuei tendo o erro 403 em "/login"

A única coisa que solucionou foi fazer um if dentro do doFilterInternal para verificar a RequestURI e nao fazer a verificação no caso de ser "/login".

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.Usuario;
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.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
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 {
        if ("/login".equals(request.getRequestURI())) {
            filterChain.doFilter(request, response);
            return;
        }
        String tokenJWT = recuperarToken(request);
        if(tokenJWT != null) {
            String subject = tokenService.getSubject(tokenJWT);
            UserDetails usuario = repository.findByLogin(subject);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }

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

    }
}

Gostaria de saber se há outra solução possível para que eu retirasse esse if dali visto que, na teoria, já estaria sendo feita essa verificação em:

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

Obrigado pela ajuda!


Edit: Criei um New Request pelo Boomerang e fiz a mesma requisição sem inserir o token e funcionou normalmente, acredito que deva ter sido algum bug no request do Boomerang.

2 respostas

Oi!

O código está correto, tanto no filter quanto nas configs de urls.

O bloqueio se poderia ocorrer para alguma url que não fosse /login ou caso a ferramenta esteja disparando a requisição /login mas com outro método HTTP que não seja POST.

solução!

eu também tive um problema semelhante vc poderia tentar resolver colocando a uri completa lá no (caso haja algo além de "/login")

req.requestMatchers(HttpMethod.POST, "/login").permitAll();

a minha URI estava mais detalhada possuindo um "/user/login" e foi isso o que eu fiz. Porém eu fiz um arquivo.txt que armazenava todas as URIs publicas que deveriam ser autorizadas mesmo sem precisar de um token e eu criei uma classe para ler esse arquivo e me gerar uma List com todas as URIs e pra cada uri eu lia e autorizava a requisição lá na classe SecurityConfig então essa parte vc ignora

*****ATENÇÃO*****
vc deve considerar que deve ter todas as dependencias anotadas com o @Autowired corretamente e tentar ao máximo referencias circulares caso haja essa possibilidade a IDE irá alertar.
O motivo de vc ter que realizar a autenticação de forma manual é que o spring não está identificando sua autenticação na classe SecurityConfiguration corretamente então vc deve ter uma atenção especia à essa classe.
Verifique também se a @SpringAplication está escaneando corretamente todos os pacotes e subpacotes de seu projeto.
    
`@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .csrf(AbstractHttpConfigurer::disable)
            .sessionManagement(session -> session
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authorizeHttpRequests(auth -> {
                try {
                    publicURIs().forEach(u -> auth.requestMatchers(u).permitAll());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                auth.anyRequest().authenticated();
            })
            .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}