Spring安全数据库身份验证示例
在以前的帖子中,我们已经看到了如何在Spring Security中使用自定义登录页面。
我们在spring-security.xml中声明了用户名和密码,但如果我们想从数据库中读取它。
在大多数情况下,我们将从数据库中读取凭据。
在本教程中,我们将使用数据库进行身份验证。
我们将使用MySQL和Hibernate进行数据库身份验证。
如果要保护Spring Web应用程序,则只需配置某些文件即可使用Spring Security发生。
我们将在Hello World示例中应用登录安全性,因此只有授权用户可以访问管理页面。
在继续之前,请首先在MySQL中配置数据库表,我们将用于身份验证。
数据库设置:
CREATE TABLE users ( username VARCHAR(45) NOT NULL , password VARCHAR(45) NOT NULL , active TINYINT NOT NULL DEFAULT 1 , PRIMARY KEY (username)); CREATE TABLE user_roles ( user_role_id int(11) NOT NULL AUTO_INCREMENT, username varchar(45) NOT NULL, role varchar(45) NOT NULL, PRIMARY KEY (user_role_id), UNIQUE KEY unique_username_role (role,username), KEY fk_username_index (username), CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username)); INSERT INTO users(username,password,active) VALUES ('igi','igi', true); INSERT INTO users(username,password,active) VALUES ('john','john', true); INSERT INTO user_roles (username, role) VALUES ('igi', 'ROLE_USER'); INSERT INTO user_roles (username, role) VALUES ('igi', 'ROLE_ADMIN'); INSERT INTO user_roles (username, role) VALUES ('john', 'ROLE_USER');
以下是在Spring MVC Hello World示例中应用Spring Security自定义登录表单的步骤。
第1步:创建Spring MVC Hello World示例名为SpringsecurityDatabaseAuthenticationExample。
它将创建基本的Spring MVC应用程序。
步骤2:将Spring Security,Hibernate和MySQL连接器添加到POM.xml。
我们需要将以下依赖性添加到POM。
pom.xml.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.igi.theitroad</groupId> <artifactId>SpringSecurityDatabaseAuthenticationExample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringSecurityDatabaseAuthenticationExample Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency> <!-- Hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Apache Commons DBCP --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies> <build> <finalName>SpringSecurityHelloWorlExample</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> </configuration> </plugin> </plugins> </build> <properties> <spring.version>4.2.1.RELEASE</spring.version> <security.version>4.0.3.RELEASE</security.version> <hibernate.version>4.3.5.Final</hibernate.version> <jdk.version>1.7</jdk.version> </properties> </project>
创建控制器和视图
第3步更改名为"helloWorldcontroller.java"的控制器类如下所示
package org.igi.theitroad.springmvc.controller; import java.security.Principal; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloWorldController { @RequestMapping("/helloworld") public ModelAndView hello(ModelMap model,Principal principal) { String loggedInUserName=principal.getName(); return new ModelAndView("hello", "userName", loggedInUserName); } @RequestMapping("/admin") public ModelAndView helloAdmin(ModelMap model,Principal principal) { String loggedInUserName=principal.getName(); return new ModelAndView("admin", "userName", loggedInUserName); } @RequestMapping(value="/login", method = RequestMethod.GET) public String login(ModelMap model) { return "login"; } @RequestMapping(value="/loginError", method = RequestMethod.GET) public String loginError(ModelMap model) { model.addAttribute("error", "true"); return "login"; } //for 403 access denied page @RequestMapping(value = "/403", method = RequestMethod.GET) public ModelAndView accesssDenied(Principal user) { ModelAndView model = new ModelAndView(); if (user != null) { model.addObject("msg", "Hi " + user.getName() + ", You can not access this page!"); } else { model.addObject("msg", "You can not access this page!"); } model.setViewName("403"); return model; } }
由于请求首先转到DispatcherServlet并将其重定向到控制器类。
这里@controller描绘了这是我们的控制器类。
@RequestMapper用于将传入的HTTP请求映射到处理程序方法(Hello()在上面的控制器中).so hello()helloworldcontroller.java的方法将处理从Dispatcher获取请求。
其中我们使用的是主体对象以在用户名中登录的当前。
它由Spring Security框架设置。
第4步:修改hello.jsp in/web-inf/pages文件夹
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Hello</title> </head> <body> ${message} <c:url value="/j_spring_security_logout" var="logoutUrl" <a href="${logoutUrl}">Log Out</a> </body> </html>
第5步:在/web-inf/pages文件夹中创建login.jsp.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <style type="text/css"> <%@include file="style.css" %> </style> <head> <title>Custom Login Page</title> </head> <body onload='document.loginForm.j_username.focus();'> <h3>Custom Login Page</h3> <% String errorString = (String)request.getAttribute("error"); if(errorString != null && errorString.trim().equals("true")){ out.println("<span class=\"dark\">Incorrect login name or password. Please try again"); } %> <form name='loginForm' action="<c:url value='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> <td><input name="reset" type="reset" </td> </tr> </table> </form> </body> </html>
我们在上面的login.jsp中使用了CSS文件。
创建Style.css文件如下。
#header { font-size:40px; } .dark { color:red; }
步骤6:在/web-inf/pages文件夹中创建admin.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Hello Admin</title> </head> <body> hello ${userName} !!! You are the admin <c:url value="/j_spring_security_logout" var="logoutUrl" <a href="${logoutUrl}">Log Out</a> </body> </html>
步骤7:在/web-inf/pages文件夹中创建403.jsp。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body> <h1>HTTP Status 403 - Access is denied</h1> <h2>${msg}</h2> <c:url value="/j_spring_security_logout" var="logoutUrl" <a href="${logoutUrl}">Log Out</a> </body> </html>
第8步:现在我们需要添加Spring 配置XML。
创建名为spring-security.xml的文件。
<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-4.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd"> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/resources/**" access="permitAll" <intercept-url pattern="/hello*" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" <intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" <form-login login-page="/login" default-target-url="/helloworld" authentication-failure-url="/loginError" <logout logout-success-url="/" logout-url="/j_spring_security_logout" <csrf disabled="true" <access-denied-handler error-page="/403" </http> <authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username, password, active from users where username=?" authorities-by-username-query="select username, role from user_roles where username=?" </authentication-provider> </authentication-manager> </beans:beans>
我们在上面的文件中使用了表单登录,因此如果用户尝试访问任何安全URL,则会根据上面的表单登录配置进行身份验证。
让我们了解Form-Login Tag Login-Page的每个属性的含义:我们需要为登录页面提供URL。
默认设置-target-url:如果身份验证成功,则应提供目标页面URL。
身份验证 - 失败 - URL:如果身份验证不成功,则应在此处提供重定向页面URL。
访问拒绝处理程序:如果用户无权访问页面,则将调用403 URL。
拦截 - URL配置哪种模式配置了什么样的安全性。
例如:如果HTTP请求URL具有模式/hello *(hello.jsp,helloworld.html),它将被访问到角色_admin和角色_user,但如果http请求url具有模式/admin *,则只能访问ROM_ADMIN
我们为逐个用户名查询和authorities-by-username-query提供了查询,以设置角色的凭据。
步骤9:SpringMVC-Dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="org.igi.theitroad.springmvc.controller" <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <mvc:annotation-driven <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" <property name="url" value="jdbc:mysql://localhost:3306/CountryData" <property name="username" value="root" <property name="password" value="igi123" </bean> <!-- Hibernate 4 SessionFactory Bean definition --> <bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> </beans>
步骤10:我们需要更改Web.xml以配置Spring Security。
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>springmvc-dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/springmvc-dispatcher-servlet.xml, /WEB-INF/spring-security.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 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> </web-app>
其中我们使用了删除了HTTP请求并将其传递给SpringSecurityFilterchain的德国滤波器。
SpringseCurityFilterchain是由Spring创建的bean,其中http元素在spring-security.xml中使用。
它维护所有过滤器的列表,负责过滤器链。
我们完成了Spring安全所需的变更。
第11步:是Maven Build的时候了。
将目标作为清洁安装(如下所示),然后单击运行
运行应用程序
第12步:右键单击项目 - >在服务器上运行AS - >运行
选择Apache Tomcat,然后单击"完成"
我们将看到以下屏幕:
单击"管理页面"链接时,我们将获取以下登录页面。