Пружинный фильтр безопасности JWT выдает 500 и HTML вместо 401 и json - PullRequest
1 голос
/ 14 июля 2020

У меня возникли проблемы с правильной работой системы безопасности, половина проблемы была решена с помощью этого Spring Boot Security не игнорирует определенные пути, которые не нужно защищать Вторая проблема - Spring игнорирует статус HTTP код при сбое и всегда выдает 500.

Когда токен JWT недействителен, я хочу вернуть ответ 401 и json. Я продолжаю получать 500 и страницу с белой этикеткой html. JwtFilter

class JwtFilter(private val tokenService: TokenService) : GenericFilterBean() {

    override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) {

        val request = req as HttpServletRequest
        val response = res as HttpServletResponse

        val httpRequest = request as HttpServletRequest
        val path = httpRequest.servletPath.toString().substring(0, 12)
        if (path == "/api/v1/auth") {
            chain.doFilter(req, res)
            return
        } else {
            val token = TokenUtil.extractToken(request as HttpServletRequest)

            if (token != null && token.isNotEmpty()) {
                try {
                    tokenService.getClaims(token)
                } catch (e: SignatureException) {
                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid JWT Signature")
                } catch (e: MalformedJwtException) {
                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid JWT token")
                } catch (e: ExpiredJwtException) {
                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Expired JWT token")
                } catch (e: UnsupportedJwtException) {
                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unsupported JWT exception")
                } catch (e: IllegalArgumentException) {
                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Jwt claims string is empty")
                }
            } else {
                throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing auth token")
            }
            chain.doFilter(req, res)
        }
    }
}

В моем классе приложения у меня также есть

@SpringBootApplication(exclude = [ErrorMvcAutoConfiguration::class])

В другом месте приложения ResponseStatusException выдает ошибку с правильным кодом и в формате JSON, например, здесь когда я генерирую исключение, ответ будет HTML как

HTTP-статус 500 - внутренняя ошибка сервера, тело {font-family: Tahoma, Arial, sans-serif; }
    h1,
    h2,
    h3,
    b {
        color: white;
        background-color: #525D76;
    }

    h1 {
        font-size: 22px;
    }

    h2 {
        font-size: 16px;
    }

    h3 {
        font-size: 14px;
    }

    p {
        font-size: 12px;
    }

    a {
        color: black;
    }

    .line {
        height: 1px;
        background-color: #525D76;
        border: none;
    }
</style>

HTTP-статус 500 - внутренняя ошибка сервера

Тип Отчет об исключении

Сообщение 401 UNAUTHORIZED «Истек срок действия токена JWT»

Описание Сервер обнаружил непредвиденное условие, которое помешало ему выполнить запрос.

Исключение

org.springframework.web.server.ResponseStatusException: 401 UNAUTHORIZED "Expired JWT token"
    events.slap.app.web.security.JwtFilter.doFilter(JwtFilter.kt:40)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

Примечание Полная трассировка стека причины root доступна в журналах сервера.

Apache Tomcat / 9.0.35

1 Ответ

1 голос
/ 15 июля 2020

Вместо того, чтобы бросать исключения в фильтре, сделайте это

    response.sendsetStatus(HttpServletResponse.SC_UNAUTHORIZED);  
    return;

или, если вам нужно сообщение,

    StringBuilder sb = new StringBuilder();
    sb.append("{ ");
    sb.append("\"error\": \"Unauthorized\" ");
    sb.append("\"message\": \"Unauthorized\"");<--- your message here
    sb.append("\"path\": \"")
      .append(request.getRequestURL())
      .append("\"");
    sb.append("} ");

    response.setContentType("application/json");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
    response.getWriter().write(sb.toString());
    return;
...