有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java OncePerRequestFilter无法设置与404不同的错误代码

我在tomcat上部署了一个Spring应用程序(不使用Spring boot)

我试图在给定条件下使用OncePerRequestFilter返回特定URL上的错误401(HttpServletResponse.SC_UNAUTHORIZED

但我总是发现一个错误:

Response code: 404

我的过滤器(移除条件):

@Component
public class MyFilter extends OncePerRequestFilter {

    private static final Logger logger = Logger.getLogger(MyFilter.class);
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not autorized");           
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            try {
                PrintWriter out = response.getWriter();
                out.write(""); // Empty
                out.flush();
            } catch (IOException e) {
                logger.error("error filtering", e);
            }
            return; // stop chain
    }    
}

我尝试使用类似的代码来previous similar answer

I believe you can response.sendError inside do Filter method.

编辑

如果我只是抛出一个异常,我会得到一个通用错误代码500

Response code: 500

编辑2

我正在onStartup方法重写WebApplicationInitializer的内部添加过滤器

FilterRegistration myFilter = servletContext.addFilter("myFilter ", MyFilter.class);
myFilter.addMappingForUrlPatterns(null, false, "/myservlet/myendpoint/*");

编辑3

此外,我的过滤器在@Componenet和它的包中包括在组件扫描中

@ComponentScan(basePackages = { "my.parent.pacakge"})

共 (2) 个答案

  1. # 1 楼答案

    只有在out.write之后执行setStatus时,它才会像预期的那样返回401

    PrintWriter out = response.getWriter();
    out.write("");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    
  2. # 2 楼答案

    我试过你的代码,效果很好。已成功返回不同的错误代码。不过我想指出几件事

    1. 方法sendError()将响应发送到客户端,并清除响应缓冲区。所以,你在它后面写的任何东西都没有用
    2. 调用setStatus()也没有用。当您调用sendError()时,HTTP响应和HTTP响应代码已经发送到上面一行中的客户端

    现在,这是我的假设,为什么你的代码不适合你,但它适合我-

    您可能获得HTTP 404的原因是您的API不存在。这可能是由于拼写错误,也可能是由于简单的无知,比如调用名为/foo/bar的API,比如/foo/bar/,即使用额外的尾部正斜杠。我相信您的过滤器正在成功执行,您一定在做一些有用的事情,而不是您在问题中解释的sendError()的示例代码。

    此外,当您在过滤器中抛出异常时,控件不会到达API,也不会进行API查找。因此,由于未处理的异常而不是HTTP 404,默认HTTP 500响应被发送到客户端