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); }
额外优化建议
- 修正
UsernamePasswordAuthenticationToken构造参数:第二个参数应为用户凭证(密码)而非权限列表,规范写法是:// 未认证时用用户名+密码 UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(tempUser.getUsername(), tempUser.getPassword(), getAuthorities(1)); // 已认证通过时用用户信息+权限 UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(tempUser, null, getAuthorities(1)); - 完善
AuthenticationManager配置:当前的AuthenticationManager未配置用户认证提供者,若后续启用authenticationManager.authenticate(authReq)会抛出异常,需添加UserDetailsService和PasswordEncoderBean来完善认证逻辑。
内容的提问来源于stack exchange,提问作者Amit Bhatiwal
相关产品推荐
相关产品推荐

