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

Spring Security FilterChain为何差异化处理@Controller与@RestController请求?

问题原因分析与解决方案

核心原因

当你使用@Controller时,返回的"home.html"是视图名称,Spring MVC会触发内部转发(forward)去查找对应的视图资源;而@RestController是@Controller + @ResponseBody的组合,返回的字符串会直接作为响应体返回,不会触发转发。

Spring Security的过滤器链默认会拦截所有请求,包括内部转发请求:

  • 用@RestController时,请求只走一次过滤器链,匹配到/home的permitAll规则,直接放行,返回字符串。
  • 用@Controller时,初始请求/home被放行,但后续转发到视图资源的路径(比如/templates/home.html,取决于你的视图解析器配置)不在permitAll列表里,过滤器链会拦截这个转发请求,触发重定向登录。

解决办法

方法1:放行视图资源的路径

在Security配置中添加视图资源所在目录的permitAll规则,比如视图文件放在/templates/或/static/下:

SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    return http
            .authorizeHttpRequests(authorize -> {
                authorize.requestMatchers("/", "/home", "/templates/**", "/static/**").permitAll();
                authorize.anyRequest().authenticated();
            })
            .formLogin(withDefaults())
            .oauth2Login(withDefaults())
            .build();
}

方法2:给方法添加@ResponseBody

如果不需要视图解析,只想返回字符串,直接在@Controller的方法上加上@ResponseBody,效果和@RestController一致:

@GetMapping("home")
@ResponseBody
public String home(){
    return "home.html";
}

方法3:配置Security不拦截内部转发

通过指定DispatcherType排除转发请求的拦截:

SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    return http
            .authorizeHttpRequests(authorize -> {
                // 放行所有转发请求
                authorize.requestMatchers(DispatcherType.FORWARD, "/**").permitAll();
                authorize.requestMatchers("/", "/home").permitAll();
                authorize.anyRequest().authenticated();
            })
            .formLogin(withDefaults())
            .oauth2Login(withDefaults())
            .build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:57:45