1. 概述
在本文中,我們將演示如何使用 Spring MVC 實現一個簡單的登錄頁面,用於處理 Spring Security 在後端進行的身份驗證。有關如何使用 Spring Security 處理登錄的詳細信息,請參閲本文深入探討配置和實現過程。
2. 登錄頁面
讓我們首先定義一個非常簡單的登錄頁面:<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>
現在,讓我們包含一個客户端檢查,以確保用户名和密碼在提交表單之前已輸入。對於此示例,我們將使用純 JavaScript,但 jQuery 也是一個不錯的選擇:
<script type="text/javascript">
function validate() {
if (document.f.username.value == "" && document.f.password.value == "") {
alert("用户名和密碼不能為空");
document.f.username.focus();
return false;
}
if (document.f.username.value == "") {
alert("用户名不能為空");
document.f.username.focus();
return false;
}
if (document.f.password.value == "") {
alert("密碼不能為空");
document.f.password.focus();
return false;
}
}
</script>
正如你所看到的,我們只是檢查用户名或密碼字段是否為空;如果為空 – 一個 JavaScript 消息框將彈出,帶有相應的消息。
3. Message Localization
Next – let’s localize the messages we’re using on the front end. There are types of such messages, and each is localized in a different manner:
- Messages generated
before the form is processed by Spring’s controllers or handlers. These messages ca be referenced in the JSP pages and are localized with Jsp/Jslt localization (see Section 4.3.) - Messages that are localized once a page has been submitted for processing by Spring (after submitting the
login form); these messages are localized using Spring MVC localization (See Section 4.2.)
3.1. The message.properties Files
In either case, we need to create a
For example, if we want to support English and Spanish error messages we would have the file:
We’re going to place these two files in the project’s classpath (
message.username=Username required
message.password=Password required
message.unauth=Unauthorized access!!
message.badCredentials=Invalid username or password
message.sessionExpired=Session timed out
message.logoutError=Sorry, error login out
message.logoutSucc=You logged out successfully
3.2. Configuring Spring MVC Localization
Spring MVC provides a
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
return cookieLocaleResolver;
}
By default, the locale resolver will obtain the locale code from the HTTP header. To force a default locale, we need to set it on the
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH);
return cookieLocaleResolver;
}
This locale resolver is a
alternatively, there is a
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
return sessionLocaleResolver;
}
Lastly, note that the
<a href="?lang=en">English</a> |
<a href="?lang=es_ES">Spanish</a>
3.3. JSP/JSLT Localization
JSP/JSLT API will be used to display localized messages that are caught in the jsp page itself. To use the jsp localization libraries we should add the following dependencies to the
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
</dependency>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
2. Add the jsp/jslt element that will point to the messages.properties files:
<fmt:setBundle basename="messages" />
3. Add the following fmt:… elements to store the messages on jsp variables:
<fmt:message key="message.password" var="noPass" />
<fmt:message key="message.username" var="noUser" />
4. Modify the login validation script we saw in Section 3 so as to localize the error messages:
<script type="text/javascript">
function validate() {
if (document.f.username.value == "" && document.f.password.value == "") {
alert("${noUser} and ${noPass}");
document.f.username.focus();
return false;
}
if (document.f.username.value == "") {
alert("${noUser}");
document.f.username.focus();
return false;
}
if (document.f.password.value == "") {
alert("${noPass}");
document.f.password.focus();
return false;
}
}
</script>
<c:if test="${param.regSucc == true}"> <div id="status"> <spring:message code="message.regSucc"> </spring:message> </div> </c:if> <c:if test="${param.regError == true}"> <div id="error"> <spring:message code="message.regError"> </spring:message> </div> </c:if>
<c:if test="${param.error != null}"> <div id="error"> <spring:message code="message.badCredentials"> </spring:message> </div> </c:if>
Notice that we are using a <spring:message …> element. This means that the error messages are generated during the Spring MVC processing.
The full login page – including the js validation and these additional status messages can be found in the github project.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> <@taglib uri="http://www.springframework.org/tags" prefix="spring"%> <c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION}"> <div id="error"> <spring:message code="message.logoutError"> </spring:message> </div> </c:if> <c:if test="${param.logSucc == true}"> <div id="success"> <spring:message code="message.logoutSucc"> </spring:message> </div> </c:if> <html> <head> <title>Logged Out</title> </head> <body> <a href="login.html">Login</a> </body> </html>
Notice that the logout page also reads the query string param logSucc, and if its value equal to true, a localized success message will be displayed.
5. Spring Security 配置
本文檔的重點是登錄流程的前端,而不是後端——因此我們將僅簡要查看安全配置的主要要點;有關完整的配置,請閲讀上一篇文章。5.1. 重定向到登錄錯誤 URL
在<form-login…/>元素中使用的以下指令將應用程序的流程重定向到處理登錄錯誤的 URL:authentication-failure-url="/login.html?error=true"
5.2. 成功註銷重定向
<logout
invalidate-session="false"
logout-success-url="/logout.html?logSucc=true"
delete-cookies="JSESSIONID" />
logout-success-url屬性僅將應用程序重定向到帶有參數的註銷頁面,以確認註銷成功。
6. 結論
在本文中,我們演示瞭如何為 Spring Security 支持的應用程序實現登錄頁面——處理登錄驗證、顯示身份驗證錯誤和消息本地化。
在下一篇文章中,我們將研究完整的註冊實施——目標是在登錄和註冊過程完全實現,以便為生產環境做好準備。