You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot自定义过滤器认证后Postman无响应问题求助

自定义认证过滤器导致接口返回空响应的解决方法

我在Spring Boot中手动实现请求认证,创建了自定义过滤器CustomeFilter、安全配置类和两个测试接口。请求/api/v1/accessPrivateRes时控制台打印"Request Authenticated ...",但Postman返回空响应;/api/v1/servercheck接口能正常返回结果。

自定义过滤器代码

public class CustomeFilter extends OncePerRequestFilter {

    private AuthenticationManager authenticationManager;

    @Autowired
    public CustomeFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager= authenticationManager;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        User tempUser = new User("ADFXFGDXGDS@Gmail.com",
                "ABC@123",
                true, true, true, true, // logging them in...
                getAuthorities(1) // type is List<GrantedAuthority>
        );
        UsernamePasswordAuthenticationToken authReq
                = new UsernamePasswordAuthenticationToken(tempUser, getAuthorities(1));
        authReq.setDetails(new WebAuthenticationDetails(request));
        SecurityContext sc= SecurityContextHolder.getContext();
        //Authentication authentication= authenticationManager.authenticate(authReq);
        sc.setAuthentication(authReq);
        HttpSession session = request.getSession(true);
        session.setAttribute("SPRING_SECURITY_CONTEXT", sc);
        System.out.println("Request Authenticated ...");
    }

    public Collection<GrantedAuthority> getAuthorities(Integer access) {
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

        if (access.compareTo(1) == 0) {
            authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        } else{
            authList.add(new SimpleGrantedAuthority("ROLE_USER"));
        }
        return authList;
    }
}

安全配置类代码

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
public class BasicSecurityConfig {

    @Autowired
    ObjectMapper objectMapper;

    @Bean
    public CustomeFilter customFilter(HttpSecurity httpSecurity) throws Exception {
            return new CustomeFilter(authManager(httpSecurity));
    }

    @Bean
    public AuthenticationEntryPoint restAuthenticationEntryPoint() {
        return (httpServletRequest, httpServletResponse, e) -> {
            Map<String, Object> errorObject = new HashMap<>();
            int errorCode = 401;
            errorObject.put("message", "Unauthorized access of protected resource, invalid credentials");
            errorObject.put("error", HttpStatus.UNAUTHORIZED);
            errorObject.put("code", errorCode);
            errorObject.put("timestamp", new Timestamp(new Date().getTime()));
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            httpServletResponse.setStatus(errorCode);
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(errorObject));
        };
    }

    @Bean
    public AuthenticationManager authManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder =
                http.getSharedObject(AuthenticationManagerBuilder.class);;
        return authenticationManagerBuilder.build();
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public DefaultSecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeHttpRequests(authz-> authz
                        .requestMatchers("api/v1/servercheck").permitAll()
                        .anyRequest().authenticated())
                .csrf().disable()
                .addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class)
                .addFilterBefore(customFilter(httpSecurity), UsernamePasswordAuthenticationFilter.class);
        return httpSecurity.build();
    }
}

测试接口代码

@GetMapping("/api/v1/accessPrivateRes")
private String accessPrivateRes() {
    return "This is your Private Res: LFOGANGJASFNASFSGPS#$NSDK#$MFGAASJGOREANSNGSKO343nsdfE@#nd@##n-eRSdfs";
}

@GetMapping("/api/v1/servercheck")
private String onServerCheckReceived() {
    return "Server Check Successful";
}

问题原因

核心问题出在自定义过滤器的doFilterInternal方法中:没有调用filterChain.doFilter(request, response)。

Spring的过滤器链是按顺序执行的,每个过滤器完成自身逻辑后,必须调用filterChain.doFilter将请求传递给下一个过滤器,最终才能到达控制器处理请求。如果省略这个步骤,请求链会在当前过滤器中断,控制器永远不会被执行,因此返回空响应。

解决方案

在doFilterInternal方法的最后添加filterChain.doFilter(request, response),让请求继续向下传递:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    User tempUser = new User("ADFXFGDXGDS@Gmail.com",
            "ABC@123",
            true, true, true, true, // logging them in...
            getAuthorities(1) // type is List<GrantedAuthority>
    );
    UsernamePasswordAuthenticationToken authReq
            = new UsernamePasswordAuthenticationToken(tempUser, getAuthorities(1));
    authReq.setDetails(new WebAuthenticationDetails(request));
    SecurityContext sc= SecurityContextHolder.getContext();
    //Authentication authentication= authenticationManager.authenticate(authReq);
    sc.setAuthentication(authReq);
    HttpSession session = request.getSession(true);
    session.setAttribute("SPRING_SECURITY_CONTEXT", sc);
    System.out.println("Request Authenticated ...");
    
    // 关键:继续执行过滤器链,让请求到达控制器
    filterChain.doFilter(request, response);
}

额外优化建议

  1. 修正UsernamePasswordAuthenticationToken构造参数:第二个参数应为用户凭证(密码)而非权限列表,规范写法是:
    // 未认证时用用户名+密码
    UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(tempUser.getUsername(), tempUser.getPassword(), getAuthorities(1));
    // 已认证通过时用用户信息+权限
    UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(tempUser, null, getAuthorities(1));
    
  2. 完善AuthenticationManager配置:当前的AuthenticationManager未配置用户认证提供者,若后续启用authenticationManager.authenticate(authReq)会抛出异常,需添加UserDetailsService和PasswordEncoder Bean来完善认证逻辑。

内容的提问来源于stack exchange,提问作者Amit Bhatiwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:44:59