ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Spring Security 登录表单示例 > 原文: [https://howtodoinjava.com/spring-security/login-form-b​​ased-spring-3-security-example/](https://howtodoinjava.com/spring-security/login-form-based-spring-3-security-example/) 学习使用[ Spring Security 教程](https://howtodoinjava.com/spring-security-tutorial/)中讨论的详细信息,将 **Spring Security 登录表单**添加到任何 Spring Web 应用程序。 > 阅读更多: [Spring Security 5 登录表单示例[为 Spring 5 更新]](https://howtodoinjava.com/spring5/security5/login-form-example/) ## 1\. 背景资料 我们学会了在链接的帖子中集成 [**Spring 3 和 Hibernate**](https://howtodoinjava.com/spring/spring-orm/spring-3-and-hibernate-integration-tutorial-with-example/) 之间。 该应用程序是简单的 Web 应用程序,它提供了一个视图,用户可以在其中添加/编辑员工。 使该应用程序安全。 本教程的**范围**是: * 只有授权用户才能访问编辑员工屏幕。 * 未经授权的用户应显示登录屏幕。 * 成功的凭据应转发到编辑员工屏幕。 * 不成功的凭据应转发到拒绝访问屏幕。 * 应该有一个注销应用程序的链接。 ## 2\. Spring Security Maven 依赖项 让我们从第一步开始,即更新项目依赖项。 由于以下原因,它将在演示中添加以下`four sub-modules`: 1. `spring-security-core`:它包含核心身份验证以及访问控制类和接口。 2. `spring-security-web`:包含过滤器和相关的 Web 安全基础结构代码。 它还启用了基于 URL 的安全性,我们将在此演示中使用它。 3. `spring-security-config`:它包含安全名称空间解析代码。 如果您使用 Spring Security XML 文件进行配置,则需要它。 4. `spring-security-taglibs`:它为访问安全信息和在 JSP 中应用安全约束提供基本支持。 `pom.xml` ```java <properties> <org.springframework.version>3.0.5.RELEASE</org.springframework.version> </properties> <!-- Spring Security --> <dependency> <groupid>org.springframework.security</groupid> <artifactid>spring-security-core</artifactid> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework.security</groupid> <artifactid>spring-security-web</artifactid> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework.security</groupid> <artifactid>spring-security-config</artifactid> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework.security</groupid> <artifactid>spring-security-taglibs</artifactid> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> ``` 现在使用“ `mvn compile`”命令更新项目中的依赖项。 ## 3\. 在`web.xml`中配置`DelegatingFilterProxy` Spring Security 的 Web 基础结构完全基于标准 Servlet 过滤器。 这些过滤器在`web.xml`文件中定义,否则 servlet 容器将忽略它们。 在 Spring Security 中,过滤器类也是在应用程序上下文中定义的 Spring Bean,因此能够利用 Spring 丰富的依赖注入机制和生命周期接口。 Spring 的 [`DelegatingFilterProxy`](http://static.springsource.org/spring/docs/2.0.8/api/org/springframework/web/filter/DelegatingFilterProxy.html) 提供了`web.xml`和应用上下文之间的链接。 `web.xml` ```java <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> ``` 如果您没有使用任何明确的过滤器定义,并且希望 spring 为您配置基本的基础架构,则如上例所示,将过滤器名称用作“ `springSecurityFilterChain`”。 请注意,您不应自己使用此 bean 名称。 将其添加到`web.xml`后,就可以开始编辑 Spring Security 配置文件了。 Web 安全服务是使用元素配置的。 同样不要忘记将安全配置文件放在上下文配置位置设置中。 `web.xml` ```java <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/employee-servlet.xml /WEB-INF/application-security.xml </param-value> </context-param> ``` 完整的`web.xml`文件如下所示: `web.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>/WEB-INF/index.jsp</welcome-file> </welcome-file-list> <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> <servlet> <servlet-name>employee</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>employee</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/employee-servlet.xml /WEB-INF/application-security.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app> ``` ## 4\. 配置登录注销安全性 正如我们在上一节中了解到的那样,将过滤器名称用作`springSecurityFilterChain`可以帮助您使用元素配置基本基础结构。 让我们先看看它是如何配置的? 我已经为这个演示编写了一个基本配置: `application-security.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/login" access="permitAll" /> <intercept-url pattern="/logout" access="permitAll" /> <intercept-url pattern="/accessdenied" access="permitAll" /> <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> <form-login login-page="/login" default-target-url="/list" authentication-failure-url="/accessdenied" /> <logout logout-success-url="/logout" /> </http> <authentication-manager alias="authenticationManager"> <authentication-provider> <user-service> <user name="lokesh" password="password" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans> ``` 让我们看看这个配置的实际含义。 * `http`:包括与配置相关的网址级别安全性。 此元素是所有与 Web 相关的名称空间功能的父级。 * `auto-config`:包括一些基本服务。 它是 ```java <http> <form-login /> <http-basic /> <logout /> </http> ``` 的简写 * `use-expressions`:这里使用表达式来保护单个 URL。 这些表达式可以是例如 `hasRole([role])`,`hasAnyRole([role1,role2])`,`permitAll`,`denyAll`等。 * `intercept-url`:这将匹配请求中请求的网址格式,并根据访问值决定要采取的操作。 * `form-login`: 当用户尝试访问任何安全的 URL 时,这将成为图片。 映射到`login-page`属性的登录页面将用于身份验证检查。 它是 spring security `login-processing-url`。 如果未提供,spring 将为用户提供内置的登录页面。 如果登录成功或由于无效的用户/密码匹配而导致登录失败,它也包含默认目标的属性。 * `logout`:如果在应用程序中调用注销,这将有助于查找下一个视图。 我正在使用基于 XML 的用户服务,即我不会去数据库进行密码验证,而是将用户名/密码组合存储在配置文件本身中。 要使用此设置王,请使用内置的内置用户详细信息服务来设置`authentication-manager`。 在更实时的应用程序中,这将是一些从远程数据库中获取数据的用户服务。 ## 5\. Spring 控制器 我将重用控制器,并将在控制器中添加其他映射和处理器方法。 这些其他 URL 是`/login`,`/logout`和`/accessdenied`。 具有所有方法处理器的更新后的控制器如下所示: `EditEmployeeController.java` ```java package com.howtodoinjava.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.howtodoinjava.entity.EmployeeEntity; import com.howtodoinjava.service.EmployeeManager; @Controller public class EditEmployeeController { @Autowired private EmployeeManager employeeManager; public void setEmployeeManager(EmployeeManager employeeManager) { this.employeeManager = employeeManager; } @RequestMapping(value = "/login", method = RequestMethod.GET) public String login(ModelMap model) { return "login"; } @RequestMapping(value = "/accessdenied", method = RequestMethod.GET) public String loginerror(ModelMap model) { model.addAttribute("error", "true"); return "denied"; } @RequestMapping(value = "/logout", method = RequestMethod.GET) public String logout(ModelMap model) { return "logout"; } @RequestMapping(value = "/", method = RequestMethod.GET) public String defaultPage(ModelMap map) { return "redirect:/list"; } @RequestMapping(value = "/list", method = RequestMethod.GET) public String listEmployees(ModelMap map) { map.addAttribute("employee", new EmployeeEntity()); map.addAttribute("employeeList", employeeManager.getAllEmployees()); return "editEmployeeList"; } @RequestMapping(value = "/add", method = RequestMethod.POST) public String addEmployee( @ModelAttribute(value = "employee") EmployeeEntity employee, BindingResult result) { employeeManager.addEmployee(employee); return "redirect:/list"; } @RequestMapping("/delete/{employeeId}") public String deleteEmplyee(@PathVariable("employeeId") Integer employeeId) { employeeManager.deleteEmployee(employeeId); return "redirect:/list"; } } ``` ## 6\. Spring 的视图 现在,我们已经使用安全配置和控制器处理器配置了我们的应用程序。 是时候编写本质上是 JSP 文件的视图了。 jsp 文件中最重要的附加内容是`login.jsp`文件。 该文件的格式包含用户名和密码字段的文本框。 让我们看看它是怎么写的: #### 6.1. `login.jsp` `login.jsp` ```java <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> <html> <body> <h1 id="banner">Login to Security Demo</h1> <form name="f" action="<c:url value='j_spring_security_check'/>" method="POST"> <table> <tr> <td>Username:</td> <td><input type='text' name='j_username' /></td> </tr> <tr> <td>Password:</td> <td><input type='password' name='j_password'></td> </tr> <tr> <td colspan="2">&nbsp;</td> </tr> <tr> <td colspan='2'><input name="submit" type="submit">&nbsp;<input name="reset" type="reset"></td> </tr> </table> </form> </body> </html> ``` 默认情况下,spring 会自动生成并配置一个[`UsernamePasswordAuthenticationFilter`](http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.html) bean。 默认情况下,此过滤器在处理 Web 表单中的登录 POST 时响应 URL `/j_spring_security_check`。 用户名字段使用“ `j_username`”,密码字段使用“ `j_password`”。 提交此表单时,`UsernamePasswordAuthenticationFilter`将匹配`application-security.xml`中身份验证提供程序设置中配置的用户名和密码。 #### 6.2. `logout.jsp` `logout.jsp` ```java < % session.invalidate(); %> You are now logged out!! <a href="//howtodoinjava.com/spring/spring-security/login-form-based-spring-3-security-example/">go back</a> ``` 该视图仅使会话无效,并提供一个链接以返回登录页面。 #### 6.3. `denied.jsp` 当用户尝试使用无效的用户名和密码组合进行身份验证时,此 jsp 文件将出现在用户屏幕中。 它将在类路径中显示`message.properties`中配置的相应消息。 `denied.jsp` ```java <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <body> <h1 id="banner">Unauthorized Access !!</h1> <hr /> <c:if test="${not empty error}"> <div style="color:red"> Your fake login attempt was bursted, dare again !!<br /> Caused : ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message} </div> </c:if> <p class="message">Access denied!</p> <a href="//howtodoinjava.com/spring/spring-security/login-form-based-spring-3-security-example/">Go back to login page</a> </body> </html> ``` ## 7\. Spring Security 登录表单演示 是时候测试应用程序了。 只需将应用程序部署在任何服务器中,例如就我而言,我正在使用 Tomcat 7.0. 现在,执行以下步骤: **7.1. 在浏览器`http://localhost:8080/Spring3HibernateIntegration`中输入 URL** 除了`/login`,`/logout`和`/accessdeni`之外,它将显示登录屏幕,所有其他 URL 都是受保护的 URL。 ![default-login-screen-spring-security](https://img.kancloud.cn/6b/53/6b53a0136248ab1e8dc5705c6555b17c_342x181.jpg) 默认登录界面 **7.2. 尝试使用用户名`"demo"`和密码`"1234"`进行身份验证** ![unauthorized-access-spring-security](https://img.kancloud.cn/9b/9d/9b9d5cd576f9709367bc76dbd971e080_383x207.jpg) 无效的用户名和密码的未经授权访问 由于用户名和密码无效,它将给出拒绝访问错误。 **7.3. 尝试使用用户名`"lokesh"`和密码`"password"`进行身份验证** ![employee-management-screen](https://img.kancloud.cn/06/e9/06e9babbc586b97be3f515200825fad0_346x361.jpg) 成功验证后的员工编辑界面 因为用户名和密码正确,它将显示员工管理屏幕。 **7.4. 单击注销链接** ![logout-spring-security](https://img.kancloud.cn/cd/e7/cde7a4c589be5484797b7b5c09933a91_227x62.jpg) 注销消息 用户将被注销,并出现登录屏幕。 我希望这个 **spring mvc 登录示例**能够对使用 xml 配置的基本 Spring Security 机制有所启发。 如果您对此 **Spring Security 登录表单示例**有任何疑问,请给我评论。 [**下载源码**](https://docs.google.com/file/d/0B7yo2HclmjI4NkU5T3NiQzdzc2s/edit?usp=sharing) 学习愉快!