我有一个Spring Boot Filter,我使用Jwt
进行身份验证。如果成功,一切都很好,我发出了Json
我的设计回复。但是,如果Authorization
标头丢失或不正确,我会使用自定义消息抛出ServletException
。这导致丑陋的Json
看起来像这样:
{
"timestamp":1453192910756,
"status":500,
"error":"Internal Server Error",
"exception":"javax.servlet.ServletException",
"message":"Invalid Authorization header.",
"path":"/api/test"
}
我希望自定义此Json
,因此我需要使用我所有其他回复的标准表单。
我的过滤器代码在这里:
public class JwtFilter extends GenericFilterBean {
@Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
System.out.println("JwtFilter");
final HttpServletRequest request = (HttpServletRequest) req;
final String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
throw new ServletException("Missing Authorization header.");
}
if (!authHeader.startsWith("Bearer ")) {
throw new ServletException("Invalid Authorization header.");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (final SignatureException e) {
throw new ServletException("Invalid token.");
}
chain.doFilter(req, res);
}
}
我尝试使用包装器来包装响应但是没有用。另一篇SO帖子说,回应并没有改变,但这甚至没有意义。
我认为正确的方法是修改ServletResponse
res
,但我无法让它发挥作用。
谢谢!
编辑:有点hacky但它有效。如果有更好的方法,请回答:
public class JwtFilter extends GenericFilterBean {
@Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
System.out.println("JwtFilter");
final HttpServletRequest request = (HttpServletRequest) req;
final String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Missing Authorization header."));
return;
}
if (!authHeader.startsWith("Bearer ")) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Invalid Authorization header."));
return;
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (Exception f) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Invalid token."));
return;
}
chain.doFilter(req, res);
}
}
答案 0 :(得分:1)
通常,在调用doFilter
之后包装响应然后修改响应输出流是正确的方法,例如
PrintWriter out = response.getWriter();
CharResponseWrapper wrapper = new CharResponseWrapper(
(HttpServletResponse)response);
chain.doFilter(request, wrapper);
CharArrayWriter caw = new CharArrayWriter();
caw.write("your json");
response.setContentLength(caw.toString().getBytes().length);
out.write(caw.toString());
out.close();
尽管如此,您的用例似乎更适合在RestController处理程序方法中处理,可能与@ExceptionHandler(ServletException.class)带注释的方法一起使用。这将是一种更通用的方法,允许您利用Spring的内容协商功能来处理JSON序列化。