1
resposta

Estou com duas duvidas no meu código. Primeira: essa forma que eu lancei exceção no quando o token está nule está correta? Segunda: eu queria que /users/login e /users/cadastro pudessem acessar sem o token, porém não está dando certo.

Filter


@Component
public class TokenFilter extends OncePerRequestFilter{

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserRepository userRepository;

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

        var token = recoverToken(request);

        UserEntity user = null;

           if (token == null) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // Define o status de resposta como 401 (Unauthorized)
                response.getWriter().write("Token não fornecido"); // Envia uma mensagem de erro ao cliente
                return;
            }

        if(token != null) {
            String subjetc = tokenService.getSubject(token);

            user = userRepository.findByEmail(subjetc);

            if(user != null) {
                var authentication = new UsernamePasswordAuthenticationToken(user, user.getId(), user.getAuthorities());

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            UserEntity userEntity = userRepository.findByEmail(subjetc);

            var authentication = new UsernamePasswordAuthenticationToken(userEntity, userEntity.getId(), userEntity.getAuthorities());
             SecurityContextHolder.getContext().setAuthentication(authentication);

        }

        filterChain.doFilter(request, response);

    }


    public String recoverToken(HttpServletRequest request) {
        String authorizationHeader = request.getHeader("Authorization");

        if(authorizationHeader != null) {
            return authorizationHeader.replace("Bearer ", "");
        }
        return null;
    }

}

Configuração

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.csrf(csrf -> csrf.disable())
                .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(req ->{
                    req.requestMatchers(HttpMethod.POST, "/users/login").permitAll();
                    req.requestMatchers(HttpMethod.POST, "/users/cadastro").permitAll();
                    req.requestMatchers(HttpMethod.GET, "/h2-console/**").permitAll();
                    req.anyRequest().permitAll();
                })
                .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    } 

queria permitir que /users/login e /users/cadastro podessem ser acessados sem token, também queria saber se a maneira que lancei a exceção quando o token é null está certo. Se alguem puder me ajudar :)

1 resposta

Olá Alisson, tudo bem?

Sobre a sua primeira dúvida, a forma como você está lançando a exceção quando o token é null está correta. Você está definindo o status da resposta como 401 (Unauthorized) e enviando uma mensagem de erro ao cliente, o que é uma boa prática.

Já sobre a sua segunda dúvida, na configuração do Spring Security que você postou, você está permitindo o acesso aos endpoints /users/login e /users/cadastro para requisições do tipo POST. No entanto, você mencionou que quer permitir o acesso sem token, o que não está acontecendo atualmente. Para permitir o acesso sem token, você pode adicionar uma condição no TokenFilter para verificar se a requisição é para um desses endpoints e, nesse caso, não verificar o token. Algo como:

if (!request.getRequestURI().equals("/users/login") && !request.getRequestURI().equals("/users/cadastro")) {
    var token = recoverToken(request);

    // Restante do código do TokenFilter
}

Dessa forma, o código dentro do if só será executado se a requisição não for para um dos endpoints que você quer permitir o acesso sem token.

Espero ter ajudado e bons estudos!