Spring Security 表單登錄

Spring MVC,Spring Security
Remote
0
06:45 PM · Nov 29 ,2025

1. 簡介

本教程將重點介紹使用 Spring Security 進行登錄。我們將在此之前的 Spring MVC 示例基礎上進行擴展,因為 Spring MVC 及其登錄機制是搭建 Web 應用程序的必要組成部分。

2. Maven 依賴項

在使用 Spring Boot 時,spring-boot-starter-security 啓動器將自動包含所有依賴項,例如 spring-security-corespring-security-webspring-security-config 等:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.3.3.RELEASE</version>
</dependency>

如果未使用 Spring Boot,請參閲 Spring Security with Maven 文章,其中描述瞭如何添加所有必需的依賴項。 spring-security-webspring-security-config 均需要使用。

3. Spring Security Java Configuration

@Configuration
@EnableWebSecurity
public class SecSecurityConfig {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        // InMemoryUserDetailsManager (see below)
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // http builder configurations for authorize requests and form login (see below)
    }
}

3.1. InMemoryUserDetailsManager

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user1 = User.withUsername("user1")
            .password(passwordEncoder().encode("user1Pass"))
            .roles("USER")
            .build();
        UserDetails user2 = User.withUsername("user2")
            .password(passwordEncoder().encode("user2Pass"))
            .roles("USER")
            .build();
        UserDetails admin = User.withUsername("admin")
            .password(passwordEncoder().encode("adminPass"))
            .roles("ADMIN")
            .build();
        return new InMemoryUserDetailsManager(user1, user2, admin);
    }

@Bean 
public PasswordEncoder passwordEncoder() { 
    return new BCryptPasswordEncoder(); 
}

3.2. Configuration to Authorize Requests

   @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf()
            .disable()
            .authorizeRequests()
            .antMatchers("/admin/**")
            .hasRole("ADMIN")
            .antMatchers("/anonymous*")
            .anonymous()
            .antMatchers("/login*")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            // ...
    }

3.3. Configuration for Form Login

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
      // ...
      .and()
      .formLogin()
      .loginPage("/login.html")
      .loginProcessingUrl("/perform_login")
      .defaultSuccessUrl("/homepage.html", true)
      .failureUrl("/login.html?error=true")
      .failureHandler(authenticationFailureHandler())
      .and()
      .logout()
      .logoutUrl("/perform_logout")
      .deleteCookies("JSESSIONID")
      .logoutSuccessHandler(logoutSuccessHandler());
      return http.build();
}
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">
  • ">

4. 將 Spring Security 添加到 Web 應用程序

為了使用上述定義的 Spring Security 配置,我們需要將其附加到 Web 應用程序。

我們將使用 WebApplicationInitializer,因此我們不需要提供 web.xml

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext sc) {

        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(SecSecurityConfig.class);

        sc.addListener(new ContextLoaderListener(root));

        sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
          .addMappingForUrlPatterns(null, false, "/*");
    }
}

注意,如果我們在使用 Spring Boot 應用程序,則不需要此初始化器。有關在 Spring Boot 中加載安全配置的更多信息,請參閲我們關於 Spring Boot 安全自動配置的文章。

5. Spring Security XML 配置

我們也將查看相應的 XML 配置。

整個項目使用 Java 配置,因此我們需要通過 Java @Configuration 類導入 XML 配置文件:

@Configuration
@ImportResource({ "classpath:webSecurityConfig.xml" })
public class SecSecurityConfig {
   public SecSecurityConfig() {
      super();
   }
}

以及 Spring Security XML 配置,webSecurityConfig.xml

<http use-expressions="true">
    <intercept-url pattern="/login*" access="isAnonymous()" />
    <intercept-url pattern="/**" access="isAuthenticated()"/>

    <form-login login-page='/login.html' 
      default-target-url="/homepage.html" 
      authentication-failure-url="/login.html?error=true" />
    <logout logout-success-url="/login.html" />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="user1Pass" authorities="ROLE_USER" />
        </user-service>
        <password-encoder ref="encoder" />
    </authentication-provider>
</authentication-manager>

<beans:bean id="encoder" 
  class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
</beans:bean>

6. Web.xml 的配置

在 Spring 4 之前,我們使用在 web.xml 中添加額外的過濾器來配置 Spring Security:

<display-name>Spring Secured Application</display-name>

<!-- Spring MVC -->
<!-- ... -->

<!-- Spring Security -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

過濾器 – DelegatingFilterProxy – 僅僅委託給一個 Spring 管理的 Bean – 即 FilterChainProxy – 該 Bean 能夠充分利用 Spring 的 Bean 生命週期管理等功能。

7. 登錄表單

登錄表單頁面將使用 Spring MVC 的簡單機制註冊視圖名稱到 URL。 此外,不需要在視圖和控制器之間進行顯式映射:

registry.addViewController("/login.html");

這對應於 login.jsp

<html>
<head></head>
<body>
   <h1>登錄</h1>
   <form name='f' action="login" method='POST'>
      <table>
         <tr>
            <td>用户名:</td>
            <td><input type='text' name='username' value=''></td>
         </tr>
         <tr>
            <td>密碼:</td>
            <td><input type='password' name='password' /></td>
         </tr>
         <tr>
            <td><input name="submit" type="submit" value="提交" /></td>
         </tr>
      </table>
  </form>
</body>
</html>

Spring 登錄表單

  • login – 表單通過 POST 請求提交到的 URL,以觸發身份驗證過程
  • username – 用户名
  • password – 密碼

8. Further Configuring Spring Login

我們簡要討論了在介紹 Spring Security 配置時登錄機制的幾個配置。現在讓我們更詳細地瞭解一下。

覆蓋 Spring Security 的大多數默認值的一個原因是隱藏應用程序使用 Spring Security 的事實。我們還希望儘量減少潛在攻擊者對應用程序所瞭解的信息。

完全配置後,登錄元素如下所示:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.formLogin()
      .loginPage("/login.html")
      .loginProcessingUrl("/perform_login")
      .defaultSuccessUrl("/homepage.html",true)
      .failureUrl("/login.html?error=true")
    return http.build();
}

或者對應的 XML 配置:

<form-login 
  login-page='/login.html' 
  login-processing-url="/perform_login" 
  default-target-url="/homepage.html"
  authentication-failure-url="/login.html?error=true" 
  always-use-default-target="true"/>

8.1. The Login Page

接下來,我們將使用 loginPage() 方法 配置一個自定義登錄頁面:

http.formLogin()
  .loginPage("/login.html")

同樣,我們可以使用 XML 配置:

login-page='/login.html'

如果未指定此項,Spring Security 將生成一個基本的 Login Form 在 /login URL。

8.2. The POST URL for Login

Spring Login 將 POST 到觸發身份驗證過程的默認 URL 是 /login, 之前是 /j_spring_security_checkSpring Security 4

我們可以使用 loginProcessingUrl 方法來覆蓋此 URL:

http.formLogin()
  .loginProcessingUrl("/perform_login")

我們可以使用 XML 配置:

login-processing-url="/perform_login"

通過覆蓋此默認 URL,我們正在隱藏應用程序實際上使用 Spring Security 的事實。此信息不應對外暴露。

8.3. The Landing Page on Success

成功登錄後,我們將重定向到一個頁面,默認情況下是 Web 應用程序的根目錄。

我們可以通過 defaultSuccessUrl() 方法 覆蓋它:

http.formLogin()
  .defaultSuccessUrl("/homepage.html")

或者使用 XML 配置:

default-target-url="/homepage.html"

如果 always-use-default-target 屬性設置為 true,則用户始終重定向到此頁面。如果該屬性設置為 false,則用户將重定向到他們之前想要訪問的上一頁。

8.4. The Landing Page on Failure

與登錄頁面類似,登錄失敗頁面由 Spring Security 自動生成在 /login?error 默認情況下。

要覆蓋它,我們可以使用 failureUrl() 方法

http.formLogin()
  .failureUrl("/login.html?error=true")

或者使用 XML:

authentication-failure-url="/login.html?error=true"

結論

在本Spring 登錄示例中,我們配置了一個簡單的身份驗證流程。我們還討論了 Spring Security 登錄表單、安全配置以及一些高級自定義選項。

當項目在本地運行時,樣板 HTML 可在以下位置訪問:

http://localhost:8080/spring-security-mvc-login/login.html
user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.