Spring 4 Security MVC实现登录注销功能完整教程与代码示例

今天我们将学习关于Spring Security登录示例的内容。在阅读本文之前,请先查看我的之前一篇文章“Spring 4安全性介绍”,以了解一些基础知识。

Spring Security 登录退出示例在这篇文章中,我们将开发一个Spring 4 MVC安全Web应用程序,通过使用内存选项来提供登录和注销功能。这个示例使用Spring注解的Spring Java配置,这意味着不使用web.xml和Spring XML配置(旧的方式)。如果您对Spring 3.x安全模块不熟悉,请首先阅读以下帖子尝试Spring安全的做法。

    1. 使用Spring MVC框架的安全示例,使用内存、UserDetailsService和JDBC认证

 

    在Servlet Web应用中使用DAO、JDBC和内存认证的Spring安全示例

Spring 4 安全模块支持以下选项来存储和管理用户凭证:

    1. 内存存储

 

    1. 关系数据库管理系统(RDBMS)

 

    1. No SQL 数据存储

 

    轻量目录访问协议(LDAP)

我们将在本例中使用“内存存储”选项。我将在接下来的帖子中讨论其他选项。我们将使用Spring 4.0.2.RELEASE,Spring STS 3.7 Suite IDE,Spring TC Server 3.1和Java 1.8以及Maven构建工具来开发此示例。

Spring Security登录示例我们打算使用Spring 4安全功能开发登录和登出逻辑。该应用程序的主要目标是不使用”web.xml”和Spring XML Bean配置,完全使用Spring注解和Java配置特性进行开发。我们将使用以下功能开发此应用程序:

    1. 欢迎页面

 

    1. 登录页面

 

    1. 首页

 

    退出功能

请使用以下步骤来开发和探索这个Spring 4安全简单登录示例。

  • Create a “Simple Spring Web Maven” Project in Spring STS Suite with the following details
   Project Name : SpringMVCSecruityMavenApp
  • Update pom.xml with the following content
<?xml version="1.0" encoding="UTF-8"?>
<project
   xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 
   https://maven.apache.org/xsd/maven-4.0.0.xsd"
   xmlns="https://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.Olivia</groupId>
	<artifactId>SpringMVCSecruityMavenApp</artifactId>
	<packaging>war</packaging>
	<version>1.0</version>

	<properties>
	    <java.version>1.8</java.version>
	    <spring.version>4.0.2.RELEASE</spring.version>
	    <spring.security.version>4.0.2.RELEASE</spring.security.version>
	    <servlet.api.version>3.1.0</servlet.api.version>
	    <jsp.api.version>2.2</jsp.api.version>
	    <jstl.version>1.2</jstl.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${servlet.api.version}</version>
		</dependency>		
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>${jsp.api.version}</version>
		</dependency>
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>
	</dependencies>	

	<build>
	    <finalName>SpringMVCSecruityMavenApp</finalName>
	    <plugins>
		<plugin>
		     <groupId>org.apache.maven.plugins</groupId>
		     <artifactId>maven-compiler-plugin</artifactId>
		     <version>3.1</version>
		     <configuration>
			<source>${java.version}</source>
			<target>${java.version}</target>
		     </configuration>
		</plugin>
		<plugin>
	           <groupId>org.apache.maven.plugins</groupId>
	           <artifactId>maven-war-plugin</artifactId>
	           <configuration>
	              <failOnMissingWebXml>false</failOnMissingWebXml>
	           </configuration>           
        	</plugin>
	    </plugins>
	</build>
</project>

如果您对“”标志不了解,请阅读本文末尾以获得关于此元素用法的良好理解。首先,使用Spring的@Controller注解开发登录控制器。LoginController.java

package com.Olivia.spring.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class LoginController {

	@RequestMapping(value = { "/"}, method = RequestMethod.GET)
	public ModelAndView welcomePage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("welcomePage");
		return model;
	}

	@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
	public ModelAndView homePage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("homePage");
		return model;
	}
	
	@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
	public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error,
	@RequestParam(value = "logout",	required = false) String logout) {
		
		ModelAndView model = new ModelAndView();
		if (error != null) {
			model.addObject("error", "Invalid Credentials provided.");
		}

		if (logout != null) {
			model.addObject("message", "Logged out from JournalDEV successfully.");
		}

		model.setViewName("loginPage");
		return model;
	}

}

代码解释:我们在“LoginController”中定义了三种方法来处理三种不同类型的客户端请求。

    1. 欢迎页面(welcomePage())将处理所有使用“/”作为URI的客户端请求。

 

    1. 主页(homePage())将处理所有使用“/homePage”作为URI的客户端请求。

 

    1. 登录页面(loginPage())将处理所有使用“/loginPage”作为URI的客户端请求。

 

    在登录页面(loginPage())中,我们将处理错误和登出消息的相关事宜。
  • Then develop a class “LoginSecurityConfig” to provide Login and Logout Security Features using Spring 4 Security API.
    LoginSecurityConfig.java
package com.Olivia.spring.secuity.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
		authenticationMgr.inMemoryAuthentication()
			.withUser("scdev")
			.password("jd@123")
			.authorities("ROLE_USER");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/homePage").access("hasRole('ROLE_USER')")
			.and()
				.formLogin().loginPage("/loginPage")
				.defaultSuccessUrl("/homePage")
				.failureUrl("/loginPage?error")
				.usernameParameter("username").passwordParameter("password")				
			.and()
				.logout().logoutSuccessUrl("/loginPage?logout"); 
		
	}
}

以下是代码的解释:在“登录安全配置”中,我们定义了两种方法来存储和管理用户凭据,并处理登录和退出安全功能。

    1. @EnableWebSecurity注解用于在任何Web应用程序中启用web安全。

 

    1. @EnableWebMVCSecurity注解用于在基于Spring MVC的Web应用程序中启用web安全。

 

    1. 注意:@EnableWebSecurity = @EnableWebMVCSecurity + 额外功能。这就是为什么在Spring 4.x框架中@EnableWebMVCSecurity注解被弃用的原因。4. “LoginSecurityConfig”类或任何用于配置Spring Security的类都应该扩展“WebSecurityConfigurerAdapter”类或实现相关接口。

 

    1. configureGlobal()方法用于存储和管理用户凭据。

 

    1. 在configureGlobal()方法中,我们可以使用authorities()方法来定义应用程序的角色,例如“ROLE_USER”。我们也可以使用roles()方法来实现相同的目的。

 

    1. authorities()方法和roles()方法之间的区别:

 

    1. authorities()方法需要完整的角色名称,如“ROLE_USER”。roles()方法只需要角色名,如“USER”。它会自动添加“ROLE_”值作为角色名称的前缀。注意:在我的后续帖子中,我们将开发另一个示例来演示“USER”、“ADMIN”等角色。

 

    1. configure(HttpSecurity http)是处理登录和注销安全的重要方法。

 

    下面的代码片段用于防止未经授权访问“/homePage”。如果您尝试直接访问该页面,我们将自动重定向到“/loginPage”页面。
.antMatchers("/homePage").access("hasRole('ROLE_USER')")

如果我们移除access(“hasRole(‘ROLE_USER’)”)方法调用,那么我们可以在没有登录到我们的应用程序的情况下访问这个页面。我们使用formLogin()和logout()方法配置了登录和注销功能。

  • Enable Spring MVC Configuration
    LoginApplicationConfig.java
package com.Olivia.spring.secuity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({ "com.Olivia.spring.*" })
@Import(value = { LoginSecurityConfig.class })
public class LoginApplicationConfig {
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
	
}

代码说明:我们使用“LoginApplicationConfig”类来定义Spring MVC视图解析器,以避免编写“web.xml”文件。

    1. @EnableWebMvc注解用于在Spring框架中启用Spring Web MVC应用程序特性。

 

    1. @Import注解用于将Spring安全配置类导入到该类中。

 

    @ComponentScan注解用于在指定的包中进行组件扫描。它等同于Spring XML配置中的”context:component-scan”。
  • Initialize Spring Security
package com.Olivia.spring.secuity.config.core;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

“SpringSecurityInitializer”用于注册DelegatingFilterProxy,并使用springSecurityFilterChain。它避免在web.xml文件中编写过多过滤器配置。- 初始化Spring MVC应用程序
“SpringMVCWebAppInitializer”类用于在基于注解的配置中初始化“DispatcherServlet”,无需web.xml文件。 SpringMVCWebAppInitializer.java

package com.Olivia.spring.secuity.config.core;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.Olivia.spring.secuity.config.LoginApplicationConfig;

public class SpringMVCWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { LoginApplicationConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
	
}

请使用中文进行改写:

这本书是关于世界历史的全面概述。它涵盖了从古代文明至现代社会的重要事件和发展。这本书既深入浅出又具有权威性,适合广大读者阅读。

    1. 当我们访问应用程序时,默认情况下SpringMVCWebAppInitializer的getServletMappings()将允许访问根URL:“/”。我们可以覆盖它以转发到不同的URL。

 

    Spring或Pivotal团队正在解决这个问题,通过引入一个注释来避免编写如此多的Java代码。请在https://jira.spring.io/browse/SPR-10359上查看。
  • Develop welcomePage.jsp file
<h3>Welcome to JournalDEV Tutorials</h3>
<a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>
  • Develop loginPage.jsp file
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<html>
<body onload='document.loginForm.username.focus();'>
	<h3>JournalDEV Tutorials</h3>

	<c:if test="${not empty error}"><div>${error}</div></c:if>
	<c:if test="${not empty message}"><div>${message}</div></c:if>

	<form name='login' action="<c:url value='/loginPage' />" method='POST'>
		<table>
			<tr>
				<td>UserName:</td>
				<td><input type='text' name='username' value=''></td>
			</tr>
			<tr>
				<td>Password:</td>
				<td><input type='password' name='password' /></td>
			</tr>
			<tr>
				<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
			</tr>
		</table>
		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	</form>
</body>
</html>
  • Develop homepage.jsp file
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
	<li>Java 8 tutorial</li>
	<li>Spring tutorial</li>
	<li>Gradle tutorial</li>
	<li>BigData tutorial</li>
</ul>

<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
	<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
  • Final Project Structure looks like this:

运行Spring Security MVC登录退出示例
这是文章《Spring 4 安全 MVC 登录注销示例》的第2部分(共2部分)。

要运行这个Spring Web应用程序,我们需要一个支持Spring 4和Java 8环境,带有Servlet 3.1.0容器的Web容器。

  • 在Spring STS套件中的Spring TC服务器上部署和运行
  • 系统会自动访问我们的应用程序欢迎页面URL,如下所示:
    • 点击”登录到JournalDEV”链接以访问登录页面。
    • 现在,提供错误的登录详细信息并点击”登录”按钮。
    • 在这里我们可以观察到此错误消息:”提供的凭据无效。”
    • 现在,提供在”LoginSecurityConfig”类中配置的正确登录详细信息。
    • 成功登录到我们的应用程序后,我们可以看到带有”注销”链接的应用程序主页。
    • 点击”注销”链接以从应用程序注销。
    • 在这里我们可以观察到我们已成功从应用程序注销,并再次重定向到登录页面。我们可以在该登录页面中看到一些注销成功的消息。

请注意:如果我们观察这个例子,我们并没有正确使用web.xml文件。由于它是一个Web应用程序,Maven会搜索web.xml文件,并在应用程序中找不到时引发一些错误。为了避免Maven相关的问题,我们需要在pom.xml文件中配置相应标志。这就是关于Spring 4安全模块简单示例的全部内容。我会在我的后续帖子中开发一些更实用的示例,如角色管理、记住我功能、WebSocket安全等等。如果您喜欢我的帖子或有任何问题/建议,请给我留言。

bannerAds