spring-session icon indicating copy to clipboard operation
spring-session copied to clipboard

custom filter response writer print data disappear with spring session

Open wuguowei19880907 opened this issue 3 months ago • 1 comments

My project is built with Spring Boot 2.7.18 and Spring Session, without using Spring Security. I plan to implement authentication using a custom filter, and when authentication fails, return a 401 status code with error information in the response. My core business logic is as follows:

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        UrlPathHelper urlPathHelper = UrlPathHelper.defaultInstance;
        final String uri = urlPathHelper.getPathWithinApplication(request);
        // final String uri = request.getRequestURI();
        final String requestMethod = request.getMethod();
        // Step1: 放行公开资源
        if (isPublicUrl(uri, requestMethod)) {
            filterChain.doFilter(request, response);
            return;
        }

        // Step2: 检查会话是否存在
        HttpSession session = request.getSession(false);
        if (session == null) {
            return401(response, ECode.E100032);
            return;
        }

        Long userId = (Long) session.getAttribute(KEY_LOGIN_USER);
        if (userId == null) {
            return401(response, ECode.E100032);
            return;
        }

        // Step3: 验证细粒度权限
        List<String> permissionList = isPermissionRequiredUrl(uri, requestMethod);

        if (!permissionList.isEmpty()) {
            // 获取用户的权限列表 adminPermissions
            Set<String> adminPermissions = adminUserManager.getAdminPermissions(userId);
            // 判断,如果用户的权限包括接口要求的权限,则通过过滤器,否则报错。
            if (!adminPermissions.containsAll(permissionList)) {
                return401(response, ECode.E100020);
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
................
    private void return401(HttpServletResponse response, ECode eCode) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json;charset=UTF-8");
        // 添加调试头信息
        response.setHeader("X-Auth-Debug", "401-returned");
        response.setHeader("X-Error-Code", String.valueOf(eCode.getNumber()));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", eCode.getNumber() + "");
        jsonObject.put("message", eCode.getMessage());
        try (PrintWriter writer = response.getWriter()) {
            writer.print(jsonObject.toJSONString());
            writer.flush();
        }
    }

However, I found that after authentication fails, the 401 status code is returned correctly, but the error information in the response body is missing. The filter registration code is as follows:

    @Bean
    public FilterRegistrationBean<AuthFilter> authFilter() {
        FilterRegistrationBean<AuthFilter> registration = new FilterRegistrationBean<>();
        registration.addUrlPatterns("/a/v2/*");
        registration.setOrder(Ordered.LOWEST_PRECEDENCE);
        return registration;
    }

I also tried using OutputStream to write the response body,

       OutputStream outputStream = response.getOutputStream();
        outputStream.write(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8));
        outputStream.flush();

but it didn't work either.

wuguowei19880907 avatar Sep 25 '25 02:09 wuguowei19880907