spring-projects / spring-projects/spring-session

custom filter response writer print data disappear with spring session

Open
#3,474 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: bug
Dominant language
Java
Stars
1.9k
Forks
1.2k
Avg merge
4h 27m
Merged PRs (30d)
55

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the custom filter's doFilterInternal method and the FilterRegistrationBean configuration, then trace how Spring Session processes the response after the filter writes the 401 body. Reproduce the behavior with the shown authentication-failure paths and verify that the status, headers, and JSON response body are all preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
authentication, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.