Spring Security 6 and JSP view rendering

I’m upgrading an application from Spring Boot 2.7 to Spring Boot 3 which includes updating to Spring Security 6.

We have the following properties set:

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

We use JSPs as a template language, where the controller returns the view file name e.g.

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

This will render the JSP page /WEB-INF/view/home.jsp

The security config is e.g.

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

}

Since upgrading, visiting localhost/ redirects the browser to localhost/WEB-INF/view/home.jsp and this returns a 403 because access to that page isn’t permitted.

If I allow access to this with .requestMatchers("/", "/WEB-INF/**").permitAll() it works OK (i.e. stays on / and renders the JSP page) but this seems like a bad idea, and an unnecessary step.

With debug logging on, Spring logs the following:

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

I cant’ see anything in Spring Security migration guide about this, does anyone know what is going on?

Update

I’ve isolated this into a clean example:

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";
    }

}

src/main/resources/application.properties:

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

src/main/webapp/WEB-INF/view/home.jsp:

hello

  • spring-boot by default with executable as jar and container of tomcat or jetty or undertow does not support jsp. You must have some specific configurations made and made them work in spring-boot 2.7 so please share them as well as those need to be migrated as well

    – 




  • Your security configuration looks wrong. Which init method are you overriding? YOu should have a method that returns a SecurityFilter from the HttpSecurity method.

    – 

  • @M.Deinum have fixed the config, apologies it was extracted for this post from a AbstractHttpConfigurer class.

    – 

  • I still miss an @EnableWebSecurity… Nonetheless I doubt the security is your issue but not everything is in your question so it is hard to get to an answer.

    – 




Something I’ve overlooked first as well.

In Spring Security 6, forwards and includes are part of the security filter by default.

See Permit FORWARD when using Spring MVC

Allowing forwards globally can be done through this additional line in security configuration.

.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()

Leave a Comment