Spring Security Form Login

1. 简介

本教程将重点介绍使用 Spring Security 登录。我们将在前面的 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配置

让我们从创建一个创建SecurityFilterChain bean的 Spring Security 配置类开始*。*

通过添加@EnableWebSecurity,我们获得了 Spring Security 和 MVC 集成支持:

@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

身份验证提供者(Authentication Provider) 由一个简单的内存中实现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);
    }

在这里,我们将使用硬编码的用户名、密码和角色配置三个用户。

从 Spring 5 开始,我们还必须定义一个密码编码器。在我们的示例中,我们将使用BCryptPasswordEncoder:

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

接下来让我们配置HttpSecurity。

3.2. 授权请求的配置

我们将从进行授权请求的必要配置开始。

在这里,我们允许对/login进行匿名访问,以便用户可以进行身份验证。我们将/admin限制为ADMIN角色并保护其他一切:

   @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()
            // ...
    }

注意: antMatchers()元素的顺序很重要;更具体的规则需要先出现,然后是更一般的规则

3.3. 表单登录配置

接下来我们将扩展上面的配置用于表单登录和注销:

@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();
}
  • loginPage() – 自定义登录页面
  • loginProcessingUrl() – 提交用户名和密码的 URL
  • defaultSuccessUrl() – 登录成功后的登陆页面
  • failureUrl() – 登录失败后的登陆页面
  • logoutUrl() – 自定义注销

4. 为Web应用添加Spring Security

要使用上面定义的 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;*只有一个额外的过滤器添加到标准的 Spring MVC web.xml中:

<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 - 它本身能够从完整的 Spring bean 生命周期管理等中受益。

7.登录表单

登录表单页面将使用将视图名称映射到 URL的直接机制向 Spring MVC 注册。此外,两者之间不需要显式控制器:

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

这当然对应于login.jsp

<html>
<head></head>
<body>
   <h1>Login</h1>
   <form name='f' action="login" method='POST'>
      <table>
         <tr>
            <td>User:</td>
            <td><input type='text' name='username' value=''></td>
         </tr>
         <tr>
            <td>Password:</td>
            <td><input type='password' name='password' /></td>
         </tr>
         <tr>
            <td><input name="submit" type="submit" value="submit" /></td>
         </tr>
      </table>
  </form>
</body>
</html>

Spring 登录表单具有以下相关工件:

  • 登录- 发布表单以触发身份验证过程的 URL
  • 用户名——用户名
  • 密码——密码

8. 进一步配置Spring登录

上面我们在介绍Spring Security Configuration的时候简单的讨论了登录机制的几个配置。现在让我们更详细地讨论一下。

覆盖 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. 登录页面

接下来我们将使用 loginPage() 方法配置自定义登录页面:

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

同样,我们可以使用 XML 配置:

login-page='/login.html'

如果我们不指定它,Spring Security 将在/login URL 生成一个非常基本的登录表单。

8.2. 用于登录的 POST URL

Spring Login 将 POST 以触发身份验证过程的默认 URL 是/login,在*Spring Security 4之前它曾经是*/j_spring_security_check

我们可以使用loginProcessingUrl 方法来覆盖这个 URL:

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

我们还可以使用 XML 配置:

login-processing-url="/perform_login"

通过覆盖此默认 URL,我们隐藏了该应用程序实际上是受 Spring Security 保护的。此信息不应从外部获得。

8.3. 成功的登录页

成功登录后,我们将被重定向到默认情况下是 Web 应用程序根目录的页面。

我们可以通过*defaultSuccessUrl()*方法覆盖它:

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

或者使用 XML 配置:

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

如果always-use-default-target属性设置为 true,则用户总是被重定向到该页面。如果该属性设置为 false,则在提示用户进行身份验证之前,用户将被重定向到他们想要访问的上一个页面。

8.4. 失败的登录页

与登录页面类似,登录失败页面由 Spring Security 在/login? 默认错误。

要覆盖它,我们可以使用 *failureUrl()*方法:

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

或者使用 XML:

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

9. 结论

在这个Spring Login Example中,我们配置了一个简单的身份验证过程。我们还讨论了 Spring Security 登录表单、安全配置和一些可用的更高级的定制。

本文的实现可以在GitHub 项目中找到——这是一个基于 Eclipse 的项目,因此应该很容易导入并按原样运行。

当项目在本地运行时,可以在以下位置访问示例 HTML:

http://localhost:8080/spring-security-mvc-login/login.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值