Information Security 9 min read

Master Spring Security: Custom Request Interception & Login Page

This tutorial demonstrates how to configure Spring Security to selectively intercept requests, permit static resources, enforce role‑based access, and replace the default login page with a custom Thymeleaf view, complete with code examples and screenshots.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Security: Custom Request Interception & Login Page

Custom Request Interception

By default, Spring Security intercepts every request, including static resources, which is often undesirable. First, create a static resource directory and configure Spring Boot to serve it under a custom prefix.

<code>spring:
  mvc:
    static-path-pattern: /resources/**
</code>

After adding Spring Security back to the project, requests to /resources/** will be redirected to the login page unless explicitly permitted.

<code>@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/resources/**")
        .permitAll();
    http.formLogin();
  }
}
</code>

To allow static resources while protecting all other endpoints, place the antMatchers rule before the anyRequest rule:

<code>@Override
protected void configure(HttpSecurity http) throws Exception {
  http.authorizeRequests()
      .antMatchers("/resources/**")
      .permitAll();
  http.authorizeRequests()
      .anyRequest()
      .authenticated();
  http.formLogin();
}
</code>

Reversing the order triggers the following exception:

<code>Caused by: java.lang.IllegalStateException: Can't configure antMatchers after anyRequest
    at org.springframework.util.Assert.state(Assert.java:76) ~[spring-core-5.3.12.jar:5.3.12]
</code>

Define two sample controllers:

<code>@RestController
@RequestMapping("/demos")
public class DemoController {
  @GetMapping("home")
  public Object home() { return "demos home"; }
}

@RestController
@RequestMapping("/api")
public class ApiController {
  @GetMapping("/{id}")
  public Object get(@PathVariable("id") Integer id) {
    return "获取 - " + id + " - 数据";
  }
}
</code>

Configure role‑based access so that /demos/** requires the USERS role and /api/** requires the ADMIN role:

<code>http.authorizeRequests().antMatchers("/demos/**").hasRole("USERS");
http.authorizeRequests().antMatchers("/api/**").hasRole("ADMIN");
http.authorizeRequests().anyRequest().authenticated();
http.formLogin();
</code>

Define in‑memory users for testing:

<code>@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication()
      .passwordEncoder(NoOpPasswordEncoder.getInstance())
      .withUser("guest").password("123456").roles("ADMIN")
      .and()
      .withUser("test").password("666666").roles("USERS");
}
</code>

Use hasAnyRole to grant access when a user possesses any one of several roles:

<code>http.authorizeRequests().antMatchers("/demos/**").hasAnyRole("USERS","AKKF","BLLE");
http.authorizeRequests().antMatchers("/api/**").hasAnyRole("ADMIN","MGR","SYSTEM");
</code>

Other useful configurations include assigning the same authority to multiple URIs and controlling access by HTTP method:

<code>http.authorizeRequests().antMatchers("/demos/**","/api/**").hasAnyAuthority("ROLE_USERS","ROLE_ADMIN");
http.authorizeRequests().antMatchers(HttpMethod.GET).permitAll();
</code>

Custom Login Page

Add Thymeleaf dependencies to the project:

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.thymeleaf&lt;/groupId&gt;
  &lt;artifactId&gt;thymeleaf-spring5&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt;
&lt;/dependency&gt;
</code>

Configure Thymeleaf template location:

<code>spring:
  thymeleaf:
    prefix: classpath:/templates/
</code>

Create login.html under src/main/resources/templates/ . The essential markup includes a form that posts to /login and displays error messages when authentication fails.

<code>&lt;div class="loginContainer"&gt;
  &lt;div class="pageTitle"&gt;&lt;h3&gt;认证登录&lt;/h3&gt;&lt;/div&gt;
  &lt;div class="loginPanel"&gt;
    &lt;div class="loginTitle"&gt;安全登录&lt;/div&gt;
    &lt;div class="loginContent"&gt;
      &lt;form method="post" action="login"&gt;
        &lt;div class="c-row"&gt;
          &lt;label&gt;安全帐号&lt;/label&gt;
          &lt;input type="text" name="username" placeholder="帐号" /&gt;
        &lt;/div&gt;
        &lt;div class="c-row"&gt;
          &lt;label&gt;安全密码&lt;/label&gt;
          &lt;input type="password" name="password" placeholder="密码" /&gt;
        &lt;/div&gt;
        &lt;div class="c-row"&gt;
          &lt;input type="checkbox" name="remember-me" /&gt;&lt;label for="remember-me"&gt;记住我&lt;/label&gt;
        &lt;/div&gt;
        &lt;div class="c-row" style="margin-top:20px;"&gt;
          &lt;button type="submit" class="btn btn-sm btn-primary"&gt;安全登录&lt;/button&gt;
        &lt;/div&gt;
      &lt;/form&gt;
      &lt;div th:if="${param.error}" class="alert alert-danger"&gt;[[${session.SPRING_SECURITY_LAST_EXCEPTION?.message}]]&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code>

Map the custom login page with a controller:

<code>@Controller
public class LoginController {
  @GetMapping("/custom/login")
  public String login() { return "login"; }
}
</code>

Finally, tell Spring Security to use this page:

<code>@Override
protected void configure(HttpSecurity http) throws Exception {
  http.csrf().disable();
  http.authorizeRequests().antMatchers("/resources/**").permitAll();
  http.authorizeRequests().antMatchers("/demos/**").hasRole("USERS");
  http.authorizeRequests().antMatchers("/api/**").hasRole("ADMIN");
  http.formLogin().loginPage("/custom/login");
}
</code>

Summary :

How to configure Spring Security to intercept requests and permit static resources.

How to enforce role‑based access for specific URI patterns.

How to replace the default login page with a custom Thymeleaf view.

Spring Bootrequest interceptionSpring Securityrole-based accesscustom login page
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.