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

Spring Boot3升级后JSP视图渲染遇Spring Security6权限问题

Spring Boot 3(Spring Security 6)升级后JSP视图跳转403问题

问题背景

正在将应用从Spring Boot 2.7升级到Spring Boot 3,同步升级Spring Security 6。现有配置如下:

MVC视图配置

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

控制器代码

@RequestMapping("/")
public String home() {
  return "home";
}

该控制器返回视图名home,会渲染/WEB-INF/view/home.jsp页面。

安全配置(升级后初始版本)

@Configuration
public class SecurityConfig  {
    @Bean
    public SecurityFilterChain config(HttpSecurity http) throws Exception {
       http.authorizeHttpRequests((auth) -> auth
          .requestMatchers("/").permitAll()
          .anyRequest().authenticated()
      );
}

问题现象

升级后访问localhost/时,浏览器会被重定向到localhost/WEB-INF/view/home.jsp,同时返回403错误——因为该路径未被授权。

临时解决方法是在安全配置中添加.requestMatchers("/", "/WEB-INF/**").permitAll(),此时功能恢复正常(停留在/并渲染JSP页面),但这种配置不合理且多余,毕竟/WEB-INF目录本就不应该允许直接访问。

开启调试日志后,Spring输出以下内容:

DEBUG [requestURL=/] o.s.security.web.FilterChainProxy        : Securing GET /
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy        : Secured GET /
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy        : Securing GET /WEB-INF/view/home.jsp
DEBUG [requestURL=/] o.s.security.web.FilterChainProxy        : Secured GET /WEB-INF/view/home.jsp

极简复现示例

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>jsptest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jsptest</name>
    <packaging>war</packaging>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Application.java

@SpringBootApplication
@Controller
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public SecurityFilterChain config(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((auth) -> auth
                        .requestMatchers("/", "/WEB-INF/view/**").permitAll()
                        .anyRequest().authenticated()
                );

        return http.build();
    }

    @RequestMapping("/")
    public String home() {
        return "home";
    }
}

application.properties

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

home.jsp

hello

问题原因

Spring Security 6调整了默认拦截的DispatcherType范围:

  • Spring Boot 2.x(Spring Security 5)默认只拦截REQUEST、ERROR、ASYNC类型的请求,FORWARD请求会被跳过。当控制器返回视图名时,Spring MVC通过FORWARD转发到JSP路径,这个转发请求不会经过Security过滤器链,因此不会触发权限校验。
  • Spring Boot 3(Spring Security 6)默认拦截所有DispatcherType,包括FORWARD。此时控制器返回视图后的转发请求会被Security拦截,而/WEB-INF/**路径未被授权,因此返回403错误。

正确解决方案

不需要开放/WEB-INF/**的直接访问权限,只需配置Spring Security放行FORWARD类型的请求,或者恢复到2.x的拦截规则即可:

方案1:放行所有FORWARD类型请求

@Configuration
public class SecurityConfig  {
    @Bean
    public SecurityFilterChain config(HttpSecurity http) throws Exception {
       http.authorizeHttpRequests((auth) -> auth
          .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
          .requestMatchers("/").permitAll()
          .anyRequest().authenticated()
      );
       return http.build();
    }
}

方案2:仅拦截REQUEST类型请求(和2.x行为一致)

import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import java.util.Collections;
import java.util.Set;
import org.springframework.web.servlet.DispatcherType;

@Configuration
public class SecurityConfig  {
    @Bean
    public SecurityFilterChain config(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
        MvcRequestMatcher mvcMatcher = new MvcRequestMatcher(introspector, "/**") {
            @Override
            protected Set<DispatcherType> getDispatcherTypes() {
                return Collections.singleton(DispatcherType.REQUEST);
            }
        };
        http
            .securityMatcher(mvcMatcher)
            .authorizeHttpRequests((auth) -> auth
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated()
            );
       return http.build();
    }
}

以上两种方案都能解决问题,且不会暴露/WEB-INF目录的直接访问权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:30:43