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

ERRO 403 EM TODO TIPO DE REQUISIÇÃO

Olá, estou com um problema em que todo tipo de requisição que faço no postman gera 403(forbidden), já tentei várias coisa porém nada funciona. Segue meu código abaixo:

-----class JWTUtil

@Component
class JWTUtil(
    private val userService: UsuarioService
) {
    @Value("\${jwt.secret}")
    private var secret: String = "$2a$12$3aDgJRIR.dkUKsqd2iPGbeFP3n/htcWkQ442mbWo9J6jY8ZftvSuW"

private val expiration: Long = 60000

private val key = Keys.hmacShaKeyFor(secret.toByteArray(StandardCharsets.UTF_8))

fun generateToken(username: String, authorities: MutableCollection<out GrantedAuthority>): String {
    return Jwts
        .builder()
        .subject(username)
        .claim("role", authorities)
        .expiration(Date(System.currentTimeMillis() + expiration))
        .signWith(key)
        .compact()
}

fun isValid(jwt: String?): Boolean {
    return try {
        Jwts.parser()
            .verifyWith(key)
            .build()
            .parseSignedClaims(jwt)
        true
    } catch (e: IllegalArgumentException) {
        false
    }
}

fun getAuthentication(jwt: String?): UsernamePasswordAuthenticationToken {
    val username = Jwts.parser()
        .verifyWith(key)
        .build()
        .parseSignedClaims(jwt)
        .payload
        .subject
    val user = userService.loadUserByUsername(username.toString())
    return UsernamePasswordAuthenticationToken(username, null, user.authorities)
}

}

5 respostas

--class SecurityConfiguration

@Configuration
        @EnableWebSecurity
        class SecurityConfiguration (
            private val configuration: AuthenticationConfiguration,
            private val jwtUtil: JWTUtil
        ) {
            @Bean
        fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
            return http
            .csrf { it.disable() }
            .authorizeHttpRequests {
                it
                    .requestMatchers("/topicos").hasAuthority("LEITURA-ESCRITA")
                    .requestMatchers("/h2-console/**").permitAll()
                    .requestMatchers(HttpMethod.POST, "/login").permitAll()
                    .anyRequest().authenticated()
            }
            .addFilterBefore(
                JWTLoginFilter(authenticationManager = configuration.authenticationManager, jwtUtil = jwtUtil),
                UsernamePasswordAuthenticationFilter().javaClass
            )
            .addFilterBefore(JWTLoginFilter(authenticationManager = configuration.authenticationManager, jwtUtil = jwtUtil), UsernamePasswordAuthenticationFilter().javaClass)
            .addFilterBefore(JWTAuthenticationFilter(jwtUtil = jwtUtil), UsernamePasswordAuthenticationFilter().javaClass)
            .sessionManagement {
                it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            }.build()
    }

    @Bean
    fun encoder(): PasswordEncoder = BCryptPasswordEncoder()
}

--class JWTLoginFilter

class JWTLoginFilter(
        private val authenticationManager: AuthenticationManager?,
        private val jwtUtil: JWTUtil,
    ) : UsernamePasswordAuthenticationFilter(authenticationManager) {

    override fun attemptAuthentication(request: HttpServletRequest?, response: HttpServletResponse?): Authentication? {
        val (username, password) = ObjectMapper().readValue(request?.inputStream, Credentials::class.java)
        val token = UsernamePasswordAuthenticationToken(username, password)
        return authenticationManager?.authenticate(token)
    }

    override fun successfulAuthentication(
        request: HttpServletRequest?,
        response: HttpServletResponse?,
        chain: FilterChain?,
        authResult: Authentication?
    ) {
        val user = (authResult?.principal as UserDetails)
        val token = jwtUtil.generateToken(user.username, user.authorities)
        response?.addHeader("Authorization", "Bearer $token")
    }

}

--JWTAuthenticationFilter

class JWTAuthenticationFilter(private val jwtUtil: JWTUtil) : OncePerRequestFilter() {
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        val token = request.getHeader("Authorization")
        val jwt = getTokenDetail(token)
        if(jwtUtil.isValid(jwt)){
            val authentication = jwtUtil.getAuthentication(jwt)
            SecurityContextHolder.getContext().authentication = authentication
        }
        filterChain.doFilter(request, response)
    }

private fun getTokenDetail(token: String?): String? {
    return token.let { jwt ->
        jwt?.startsWith("Bearer ")
        jwt?.substring(7, jwt.length)
    }
}

}

Olá, Pedro, tudo bem?

O erro 403 (Forbidden) que você está enfrentando geralmente indica que a requisição está sendo feita, mas não tem as permissões necessárias para acessar o recurso. Analisando seu código, alguns pontos podem estar causando esse problema:

  1. Permissões no SecurityConfiguration: no seu método securityFilterChain, você especifica que o acesso a "/topicos" requer a autoridade "LEITURA-ESCRITA". Verifique se o usuário que está tentando acessar esse endpoint realmente possui essa autorização. Você pode conferir isso no momento em que o token JWT é gerado e se as autoridades estão sendo corretamente atribuídas ao usuário.

    Exemplo: caso esteja testando com Postman, assegure-se de que o token JWT que você está usando está associado a um usuário com a autoridade apropriada.

  2. Verificação do Token JWT: no filtro JWTAuthenticationFilter, é importante garantir que o token JWT está sendo extraído corretamente e que o método isValid está retornando true. Tente adicionar alguns logs para verificar se o token está sendo processado como esperado.

    Exemplo: adicione um log antes da linha if(jwtUtil.isValid(jwt)){ para verificar qual token está sendo recebido.

  3. CSRF Desativado: como você desativou a proteção CSRF com csrf { it.disable() }, esse não deve ser um problema, mas é sempre bom lembrar que, se você tiver outros filtros ou configurações de segurança aplicadas, isso pode afetar a permissão das requisições.

Se, após essas verificações, o problema persistir, peço que compartilhe todo o seu projeto usando o GitHub ou Drive do Google, assim poderei investigar mais a fundo.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.
solução!

Boa tarde, Armano. Essa questão de token faz sentido, o problema é que não consigo realizar nem o "/login" no postman. Ou seja, não consigo pegar um token sem relizar o cadastro com o email e a senha. O "/login" está como permitAll(), mas retorna 403. Infelizmente não estou conseguindo fazer upload do postman, mas o erro é 403 quando passo o campo, username e password. Conferi no banco h2 e os dados do usermane que é o email é igual.

    class SecurityConfiguration (
                private val configuration: AuthenticationConfiguration,
                private val jwtUtil: JWTUtil
            ) {
                @Bean
            fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
                return http
                .csrf { it.disable() }
                .authorizeHttpRequests {
                    it
                        .requestMatchers("/topicos").hasAuthority("LEITURA-ESCRITA")
                        .requestMatchers("/h2-console/**").permitAll()
                        .requestMatchers(HttpMethod.POST, "/login").permitAll()
                        .anyRequest().authenticated()
                }
                

CREATE TABLE usuario
    (
        id bigint           not null auto_increment,
        nome varchar(50)    not null,
        email varchar(50)   not null,
        primary key(id)
    );

INSERT INTO usuario VALUES (1, 'ana', 'ana@gmail.com');