Spring security JWT过滤器抛出500和HTML而不是401和json

Bri*_*ian 12 spring spring-security spring-boot

我在确保安全性正常工作方面遇到了麻烦,一半的问题已通过此解决\n Spring Boot Security 不会忽略某些不需要保护的路径\n第二个问题是 spring 在失败时忽略 HTTP 状态代码,并且始终投出 500 分。

\n

当 JWT 令牌无效时,我想返回 401 和 json 响应。我不断收到 500 和白色标签 html 页面。\nJwtFilter

\n
class JwtFilter(private val tokenService: TokenService) : GenericFilterBean() {\n\n    override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) {\n\n        val request = req as HttpServletRequest\n        val response = res as HttpServletResponse\n\n        val httpRequest = request as HttpServletRequest\n        val path = httpRequest.servletPath.toString().substring(0, 12)\n        if (path == "/api/v1/auth") {\n            chain.doFilter(req, res)\n            return\n        } else {\n            val token = TokenUtil.extractToken(request as HttpServletRequest)\n\n            if (token != null && token.isNotEmpty()) {\n                try {\n                    tokenService.getClaims(token)\n                } catch (e: SignatureException) {\n                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid JWT Signature")\n                } catch (e: MalformedJwtException) {\n                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid JWT token")\n                } catch (e: ExpiredJwtException) {\n                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Expired JWT token")\n                } catch (e: UnsupportedJwtException) {\n                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unsupported JWT exception")\n                } catch (e: IllegalArgumentException) {\n                    throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Jwt claims string is empty")\n                }\n            } else {\n                throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing auth token")\n            }\n            chain.doFilter(req, res)\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在我的应用程序类中我也有

\n
@SpringBootApplication(exclude = [ErrorMvcAutoConfiguration::class])\n
Run Code Online (Sandbox Code Playgroud)\n

应用程序中的其他任何地方 ResponseStatusException 都会以正确的代码和 JSON 格式抛出错误,例如,当我抛出异常时,响应将是 HTML 格式

\n

<!doctype html>

\n\n\n HTTP 状态 500 \xe2\x80\x93 内部服务器错误\n \n 正文 {\n 字体系列:Tahoma、Arial、sans-serif;\n }\n
    h1,\n    h2,\n    h3,\n    b {\n        color: white;\n        background-color: #525D76;\n    }\n\n    h1 {\n        font-size: 22px;\n    }\n\n    h2 {\n        font-size: 16px;\n    }\n\n    h3 {\n        font-size: 14px;\n    }\n\n    p {\n        font-size: 12px;\n    }\n\n    a {\n        color: black;\n    }\n\n    .line {\n        height: 1px;\n        background-color: #525D76;\n        border: none;\n    }\n</style>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n

HTTP 状态 500 \xe2\x80\x93 内部服务器错误

\n\n

类型异常报告

\n

消息401 UNAUTHORIZED“JWT 令牌过期”

\n

说明服务器遇到意外情况,无法满足请求。\n

\n

例外

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

注意服务器日志中提供了根本原因的完整堆栈跟踪。

\n\n

阿帕奇汤姆猫/9.0.35

\n\n\n

Kav*_*lai 10

不要在过滤器中抛出异常,而是这样做

    response.sendsetStatus(HttpServletResponse.SC_UNAUTHORIZED);  
    return;
Run Code Online (Sandbox Code Playgroud)

或者如果您也想留言

    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;
Run Code Online (Sandbox Code Playgroud)