4.3.2 创建用户登录页面

默认的登录页面比你开始时使用的笨拙的 HTTP 基本对话框要好得多,但它仍然相当简单,不太适合 Taco Cloud 应用程序的其余部分。

要替换内置的登录页面,首先需要告诉 Spring Security 自定义登录页面的路径。这可以通过调用传递给 configure() 的 HttpSecurity 对象上的 formLogin() 来实现:

  1. @Override
  2. protected void configure(HttpSecurity http) throws Exception {
  3. http
  4. .authorizeRequests()
  5. .antMatchers("/design", "/orders")
  6. .access("hasRole('ROLE_USER')")
  7. .antMatchers(“/”, "/**").access("permitAll")
  8. .and()
  9. .formLogin()
  10. .loginPage("/login");
  11. }

请注意,在调用 formLogin() 之前,需要使用对 and() 的调用来连接这一部分的配置和前面的部分。and() 方法表示已经完成了授权配置,并准备应用一些额外的 HTTP 配置。在开始新的配置部分时,将多次使用 and()。

连接之后,调用 formLogin() 开始配置自定义登录表单。之后对 loginPage() 的调用指定了将提供自定义登录页面的路径。当 Spring Security 确定用户未经身份验证并且需要登录时,它将把用户重定向到此路径。

现在需要提供一个控制器来处理该路径上的请求。因为你的登录页面非常简单 —— 除了一个视图什么都没有 —— 在 WebConfig 中声明它为一个视图控制器是很容易的。下面的 addViewControllers() 方法在将 “/” 映射到主控制器的视图控制器旁边设置登录页面视图控制器:

  1. @Override
  2. public void addViewControllers(ViewControllerRegistry registry) {
  3. registry.addViewController("/").setViewName("home");
  4. registry.addViewController("/login");
  5. }

最后,需要定义 login 页面视图本身,因为使用 Thymeleaf 作为模板引擎,下面的 Thymeleaf 模板应该做得很好:

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml"
  3. xmlns:th="http://www.thymeleaf.org">
  4. <head>
  5. <title>Taco Cloud</title>
  6. </head>
  7. <body>
  8. <h1>Login</h1>
  9. <img th:src="@{/images/TacoCloud.png}"/>
  10. <div th:if="${error}">
  11. Unable to login. Check your username and password.
  12. </div>
  13. <p>New here? Click<a th:href="@{/register}">here</a> to register.</p>
  14. <!-- tag::thAction[] -->
  15. <form method="POST" th:action="@{/login}" id="loginForm">
  16. <!-- end::thAction[] -->
  17. <label for="username">Username: </label>
  18. <input type="text" name="username" id="username" /><br/>
  19. <label for="password">Password: </label>
  20. <input type="password" name="password" id="password" /><br/>
  21. <input type="submit" value="Login"/>
  22. </form>
  23. </body>
  24. </html>

关于这个登录页面需要注意的关键事情是,它发布到的路径以及用户名和密码字段的名称。默认情况下,Spring Security 在 /login 监听登录请求,并期望用户名和密码字段命名为 username 和 password。但是,这是可配置的。例如,以下配置自定义路径和字段名:

  1. .and()
  2. .formLogin()
  3. .loginPage("/login")
  4. .loginProcessingUrl("/authenticate")
  5. .usernameParameter("user")
  6. .passwordParameter("pwd")

这里,指定 Spring Security 应该监听请求 /authenticate 请求以处理登录提交。此外,用户名和密码字段现在应该命名为 user 和 pwd。

默认情况下,当 Spring Security 确定用户需要登录时,成功的登录将直接将用户带到他们所导航到的页面。如果用户要直接导航到登录页面,成功的登录将把他们带到根路径(例如,主页)。但你可以通过指定一个默认的成功页面来改变:

  1. .and()
  2. .formLogin()
  3. .loginPage("/login")
  4. .defaultSuccessUrl("/design")

按照这里的配置,如果用户在直接进入登录页面后成功登录,那么他们将被引导到 /design 页面。

另外,可以强制用户在登录后进入设计页面,即使他们在登录之前已经在其他地方导航,方法是将 true 作为第二个参数传递给 defaultSuccessUrl:

  1. .and()
  2. .formLogin()
  3. .loginPage("/login")
  4. .defaultSuccessUrl("/design", true)

现在已经处理了自定义登录页面,让我们来看看身份验证的另一面 —— 如何让用户登出。