创建自定义登录表单
本指南建立在Hello Spring MVC安全Java配置之上,以解释如何使用Spring Security Java Configuration配置和使用自定义登录表单。
设置样本
本节概述如何在Spring Tool Suite(STS)中设置工作区,以便您可以按照本指南进行操作。下一节概述了如何将Spring Security应用到现有应用程序的一般步骤。虽然您可以简单地将这些步骤应用于现有的应用程序,但我们鼓励您遵循本指南以降低复杂性。
获取示例项目
将Spring Security发行版解压缩到已知位置,并将其记录为SPRING_SECURITY_HOME。
导入hellomvc示例应用程序
为了遵循,我们鼓励您将hellomvc示例应用程序导入到您的IDE中。您可以使用任何您喜欢的IDE,但本指南中的说明将假设您使用的是Spring Tool Suite(STS)。
已完成的示例应用程序可以在SPRING_SECURITY_HOME / samples / javaconfig / form中找到 |
-
如果您没有安装STS,请从https://spring.io/tools下载STS
-
启动STS并使用以下步骤将示例应用程序导入到STS中:
-
文件→导入
-
现有的Maven项目
-
点击下一步>
-
点击浏览...
-
导航到样本(即SPRING_SECURITY_HOME / samples / javaconfig / hellomvc)并单击确定
-
点击完成
-
运行hellomvc应用程序
在下面的练习中,我们将修改spring-security-samples-javaconfig-hellomvc应用程序。在进行任何更改之前,最好验证样本是否正常工作。执行以下步骤以确保spring-security-samples-javaconfig-hellomvc能够正常工作。
-
右键单击spring-security-samples-javaconfig-hellomvc应用程序
-
选择运行方式→在服务器上运行
-
选择最新的tc服务器
-
点击完成
确认应用程序正在运行:
-
显示用户收件箱的页面可以在使用用户名用户和密码密码进行验证之后在http:// localhost:8080 / sample /中看到。
-
尝试点击撰写链接并创建一条消息。应显示消息详细信息。
-
现在点击收件箱链接并查看列出的消息。您可以点击摘要链接查看再次显示的详细信息。
覆盖默认配置(HttpSecurity)方法
WebSecurityConfigurerAdapter
提供了一些方便的默认设置来快速启动和运行我们的应用程序。但是,我们的登录表单看起来不像我们的其他应用程序。我们来看看我们如何更新配置来使用自定义表单。
默认配置(HttpSecurity)
配置(HttpSecurity)方法的默认配置如下所示:
protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .and() .httpBasic(); }
该配置可确保:
每个请求都需要用户进行身份验证 | |
支持基于表单的身份验证 | |
支持HTTP基本认证 |
配置自定义登录页面
我们希望确保我们能够弥补在更新中覆盖这些默认值。打开SecurityConfig
并插入configure方法,如下所示:
// ... import org.springframework.security.config.annotation.web.builders.HttpSecurity; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login"); } // ... }
该行loginPage("/login")
指示Spring Security
-
当需要认证时,将浏览器重定向到/登录
-
我们负责在/ login请求时呈现登录页面
-
当认证尝试失败时,将浏览器重定向到/ login?错误(因为我们没有另外指定)
-
当/ login?错误被请求时,我们负责渲染失败页面
-
当我们成功注销时,将浏览器重定向到/ login?注销(因为我们没有另外指定)
-
我们负责在/ login?logout请求时呈现注销确认页面
继续并启动服务器并尝试访问http:// localhost:8080 / sample /以查看我们配置的更新。在许多浏览器中,您会看到类似于此网页的重定向循环错误。发生什么事?
授予对未经身份验证的用户的访问权限
问题是Spring Security正在保护对我们自定义登录页面的访问。特别是以下情况正在发生:
-
我们向我们的Web应用程序提出请求
-
Spring Security认为我们没有通过身份验证
-
我们被重定向到/登录
-
浏览器请求/登录
-
Spring Security认为我们没有通过身份验证
-
我们被重定向到/登录 ...
为了解决这个问题,我们需要指示Spring Security允许任何人访问/ login URL。我们可以通过以下更新轻松完成此操作:
// ... @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll(); } // ... }
方法formLogin().permitAll()
声明指示Spring Security允许任何访问任何与之关联的URL(即/ login和/ login?错误)formLogin()
。
授予对formLogin() URL的访问权限并未默认完成,因为Spring Security需要对允许和不允许的内容作出某些假设。为了安全起见,最好确保授予资源访问权限是明确的。 |
启动服务器并尝试访问http:// localhost:8080 / sample /以查看我们配置的更新。你现在应该得到一个500错误,说明错误解析模板“登录”。
创建一个登录页面
在Spring Web MVC中,创建我们的登录页面有两个步骤:
-
创建一个控制器
-
创建一个视图
配置登录视图控制器
在Spring Web MVC中,第一步是确保我们有一个可以指向我们视图的控制器。由于我们的项目将javaconfig / messages项目添加为依赖项,并且它包含用于/ login的视图控制器,所以我们不需要在我们的应用程序中创建控制器。作为参考,你可以看到下面的配置:
// ... @EnableWebMvc @ComponentScan("org.springframework.security.samples.mvc") public class WebMvcConfiguration implements WebMvcConfigurer { // ... @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); } }
创建一个登录视图
我们现有的配置意味着我们所需要做的就是创建一个包含以下内容的login.html文件:
<html xmlns:th="http://www.thymeleaf.org"> <head th:include="layout :: head(title=~{::title},links=~{})"> <title>Please Login</title> </head> <body th:include="layout :: body" th:with="content=~{::content}"> <div th:fragment="content"> <form name="f" th:action="@{/login}" method="post"> <fieldset> <legend>Please Login</legend> <div th:if="${param.error}" class="alert alert-error"> Invalid username and password. </div> <div th:if="${param.logout}" class="alert alert-success"> You have been logged out. </div> <label for="username">Username</label> <input type="text" id="username" name="username"/> <label for="password">Password</label> <input type="password" id="password" name="password"/> <div class="form-actions"> <button type="submit" class="btn">Log in</button> </div> </fieldset> </form> </div> </body> </html>
我们提交我们的用户名和密码的URL与我们的登录表单(即/ login)相同,但使用POST而不是GET。 | |
当验证失败时,浏览器被重定向到/ login?错误,因此我们可以通过检测参数错误是否为非空来显示错误消息。 | |
当我们成功注销后,浏览器被重定向到/ login?logout,因此我们可以通过检测参数注销是否为非空来显示注销成功消息。 | |
用户名应该存在于HTTP参数用户名中 | |
密码应该存在于HTTP参数密码中 |
不要显示关于验证失败原因的详细信息。例如,我们不希望显示用户不存在,因为这会告诉攻击者他们应该尝试使用不同的用户名。 |
我们使用Thymeleaf自动将CSRF令牌添加到我们的表单中。如果我们不使用Thymleaf或Spring MVC taglib,我们也可以使用手动添加CSRF令牌<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 。 |
启动服务器并尝试访问http:// localhost:8080 / sample /以查看我们配置的更新。我们现在看到了我们的登录页面,但它看起来并不漂亮。问题是我们没有授予对css文件的访问权限。
授予对剩余资源的访问权
我们需要更新我们的配置,以允许任何人访问我们的资源和我们的注销页面。更新配置,如下所示:
// ... @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } // ... }
这允许任何人访问以/ resources /开头的URL 。由于这是我们的CSS,JavaScript和图像存储的地方,我们所有的静态资源都可以被任何人查看。 | |
正如您所期望的那样,logout().permitAll() 允许任何用户请求注销并查看注销成功URL。 |
重新启动服务器并尝试访问http:// localhost:8080 / sample /以查看我们配置的更新。我们现在看到一个看起来像我们应用程序其余部分的自定义登录页面。
-
尝试输入无效的用户名和密码。你会看到我们的错误消息显示。
-
尝试输入有效的用户名(用户名)和密码(密码)。您将成功通过身份验证。
-
尝试单击注销按钮。您会看到我们的注销成功消息
结论
您现在应该知道如何使用Spring Security的Java配置添加自定义登录表单。要了解更多信息,请参阅Spring Security Guides索引页面。