Spring 4 Security MVC登录注销示例

Today we will learn about Spring Security Login Example. Before reading this post, please go through my previous post at “Introduction to Spring 4 Security” to get some basics.

今天我们将学习Spring Security登录示例 。 在阅读本文之前,请仔细阅读我以前的文章“ Spring 4 Security简介”以获取一些基础知识。

Spring Security登录注销示例 (Spring Security Login Logout Example)

In this post, we are going to develop Spring 4 MVC Security Web Application to provide Login and Logout features by using In-Memory option. This example uses Spring Java Config with Spring Annotations, that means without using web.xml and Spring XML Configuration(Old Style).

在本文中,我们将开发Spring 4 MVC Security Web应用程序,以通过使用In-Memory选项提供登录和注销功能。 这个例子使用带有Spring Annotations的Spring Java Config,这意味着不使用web.xml和Spring XML Configuration(旧样式)。

If you are not familiar with Spring 3.x Security Module, please go through the following posts first to taste the Spring Security Recipe.

如果您不熟悉Spring 3.x Security Module,请先阅读以下文章以品尝Spring Security Recipe。

  1. Spring MVC Security Example using in-memory, UserDetailsService and JDBC Authentication

    使用内存,UserDetailsS​​ervice和JDBC身份验证的Spring MVC安全性示例
  2. Spring Security in Servlet Web Application using DAO, JDBC, In-Memory authentication

    Servlet Web Application中的Spring Security使用DAO,JDBC,内存中身份验证

Spring 4 Security Module supports the following options to store and manage User Credentials:

Spring 4 Security Module支持以下选项来存储和管理用户凭证:

  1. In-Memory Store

    内存中存储
  2. Relations Databases(RDBMS)

    关系数据库(RDBMS)
  3. No SQL Data Stores

    没有SQL数据存储
  4. LDAP

    LDAP

We will use “In-Memory Store” option in this example. We will discuss other options in my coming posts.

在此示例中,我们将使用“内存中存储”选项。 我们将在我的后续文章中讨论其他选项。

We are going to use Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 with Java 1.8 and Maven build tool to develop this example.

我们将使用Spring 4.0.2.RELEASE,Spring STS 3.7 Suite IDE,带有Java 1.8的Spring TC Server 3.1和Maven构建工具来开发此示例。

Spring Security登录示例 (Spring Security Login Example)

We are going to develop a Login and Logout logic using Spring 4 Security Features. The main aim of this application is that developing an application without using “web.xml” and without writing a single line of Spring XML Beans Configuration. That means we are going to use Spring Java Config feature with Spring Annotations.

我们将使用Spring 4 Security Feature开发一个Login和Logout逻辑。 该应用程序的主要目的是在不使用“ web.xml”并且不编写任何一行Spring XML Beans Configuration的情况下开发应用程序。 这意味着我们将使用带有Spring Annotations的Spring Java Config功能。

We will develop this application with the following features:

我们将使用以下功能开发此应用程序:

  1. Welcome Page

    欢迎页面
  2. Login Page

    登录页面
  3. Home Page

    主页
  4. Logout Feature

    登出功能

Please use the following steps to develop and explore this Spring 4 Security Simple Login Example.

请使用以下步骤来开发和探索此Spring 4 Security简单登录示例。

  • Create a “Simple Spring Web Maven” Project in Spring STS Suite with the following details

    在Spring STS Suite中使用以下详细信息创建“ Simple Spring Web Maven”项目
Project Name : SpringMVCSecruityMavenApp
  • Update pom.xml with the following content

    使用以下内容更新pom.xml
  • <?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.journaldev</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>

    NOTE:-
    If you are not aware of “<failOnMissingWebXml>” flag, please read at the end of this post to get a good understanding of this element usage.

    注意:-
    如果您不知道“ <failOnMissingWebXml>”标志,请阅读本文结尾处的内容,以更好地了解此元素的用法。

  • First, Develop Login Controller by using Spring’s @Controller annotation.

    首先,使用Spring的@Controller注释开发Login Controller。
  • LoginController.java

    LoginController.java

    package com.journaldev.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;
    	}
    
    }

    Code Explanation:-
    We have defined three methods in “LoginController” to handle three different kinds of Client Requests

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

    1. welcomePage() will handle all client requests which are using “/” URI.

      welcomePage()将处理所有使用“ /” URI的客户端请求。
    2. homePage() will handle all client requests which are using “/homePage” URI.

      homePage()将处理所有使用“ / homePage” URI的客户端请求。
    3. loginPage() will handle all client requests which are using “/loginPage” URI.

      loginPage()将处理所有使用“ / loginPage” URI的客户端请求。
    4. In loginPage(), we have take care of handling error and logout messages.

      在loginPage()中,我们负责处理错误和注销消息。
  • Then develop a class “LoginSecurityConfig” to provide Login and Logout Security Features using Spring 4 Security API.

    然后开发一个类“ LoginSecurityConfig”,以使用Spring 4 Security API提供登录和注销安全功能。
  • LoginSecurityConfig.java

    LoginSecurityConfig.java

    package com.journaldev.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("journaldev")
    			.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"); 
    		
    	}
    }

    Code Explanation:-
    We have defined two methods in “LoginSecurityConfig” to store and manage User Credentials and take care of Login and Logout Security features.

    代码说明:
    我们在“ LoginSecurityConfig”中定义了两种方法来存储和管理用户凭据,并注意登录和注销安全功能。

    1. @EnableWebSecurity Annotation is used to enable web security in any web application.

      @EnableWebSecurity批注用于在任何Web应用程序中启用Web安全。
    2. @EnableWebMVCSecurity Annotation is used to enable web security in Spring MVC based web application.

      @EnableWebMVCSecurity Annotation用于在基于Spring MVC的Web应用程序中启用Web安全。
    3. NOTE:-
      @EnableWebSecurity = @EnableWebMVCSecurity + Extra features.
      That’s why @EnableWebMVCSecurity Annotation is deprecated in Spring 4.x Framework.

      注意:-
      @EnableWebSecurity = @EnableWebMVCSecurity +其他功能。
      这就是在Spring 4.x Framework中不推荐使用@EnableWebMVCSecurity Annotation的原因。

    4. “LoginSecurityConfig” class or any class which is designated to configure Spring Security, should extend “WebSecurityConfigurerAdapter” class or implement related interface.

      “ LoginSecurityConfig”类或任何指定用于配置Spring Security的类应扩展“ WebSecurityConfigurerAdapter”类或实现相关接口。
    5. configureGlobal() method is used to store and mange User Credentials.

      configureGlobal()方法用于存储和管理用户凭证。
    6. In configureGlobal() method, we can use authorities() method to define our application Roles like “ROLE_USER”. We can also use roles() method for same purpose.

      在configureGlobal()方法中,我们可以使用Authority()方法来定义应用程序角色,例如“ ROLE_USER”。 我们也可以出于相同目的使用role()方法。
    7. Difference between authorities() and roles() methods:

      Authoritys()和Roles()方法之间的区别:
    8. authorities() needs a complete role name like “ROLE_USER”
      roles() needs a role name like “USER”. It will automatically add “ROLE_” value to this “USER” role name.

      NOTE:- We will develop another example to demonstrate Roles like “USER”,”ADMIN” in my coming posts.

      Authority()需要一个完整的角色名称,例如“ ROLE_USER”
      Roles()需要一个角色名称,例如“ USER”。 它将自动向该“ USER”角色名称添加“ ROLE_”值。

      注意:-我们将开发另一个示例,在我的后续文章中演示诸如“ USER”,“ ADMIN”之类的角色。

    9. Important method to take care of Login and Logout Security is configure(HttpSecurity http)

      配置登录和注销安全的重要方法是configure(HttpSecurity http)
    10. The following code snipped is used to avoid unauthorized access to “/homePage”. If you try to access this page directly, we will redirected to “/loginPage” page automatically.

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

      If we remove access(“hasRole(‘ROLE_USER’)”) method call, then we can access this page without login to our application.

      如果我们删除了access(“ hasRole('ROLE_USER')”)方法调用,那么我们无需登录应用程序即可访问此页面。

    12. We have configured login and logout features using formLogin() and logout() methods.

      我们已经使用formLogin()和logout()方法配置了登录和注销功能。
  • Enable Spring MVC Configuration

    启用S​​pring MVC配置
  • LoginApplicationConfig.java

    LoginApplicationConfig.java

    package com.journaldev.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.journaldev.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;
    	}
    	
    }

    Code Explanation:-
    We use “LoginApplicationConfig” class to define Spring MVC View Resolvers to avoid writing “web.xml” file.

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

    1. @EnableWebMvc Annotation is used to enable Spring Web MVC Application Features in Spring Framework

      @EnableWebMvc批注用于在Spring Framework中启用Spring Web MVC应用程序功能
    2. @Import Annotation is used to import Spring Security Configuration class into this class.

      @Import Annotation用于将Spring Security Configuration类导入该类。
    3. @ComponentScan Annotation is used to do component scanning in the specified package. It is equal to “<context:component-scan>” in Spring XML Configuration.

      @ComponentScan批注用于在指定的程序包中进行组件扫描。 它等于Spring XML Configuration中的“ <context:component-scan>”。
  • Initialize Spring Security

    初始化Spring Security
  • package com.journaldev.spring.secuity.config.core;
    
    import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
    
    public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
    
    }

    “SpringSecurityInitializer” is used to register the DelegatingFilterProxy to use the springSecurityFilterChain. It avoids writing Filters configuration in web.xml file.

    “ SpringSecurityInitializer”用于注册DelegatingFilterProxy以使用springSecurityFilterChain。 这样可以避免在web.xml文件中编写过滤器配置。

  • Initialize Spring MVC Application

    初始化Spring MVC应用程序
  • “SpringMVCWebAppInitializer” class is used to initialize “DispatcherServlet” without web.xml file in a Annotation based configuration.

    “ SpringMVCWebAppInitializer”类用于在基于注释的配置中在没有web.xml文件的情况下初始化“ DispatcherServlet”。

    SpringMVCWebAppInitializer.java

    SpringMVCWebAppInitializer.java

    package com.journaldev.spring.secuity.config.core;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    import com.journaldev.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[] { "/" };
    	}
    	
    }

    NOTE:-

    注意:-

    1. When we access our application, by default SpringMVCWebAppInitializer’s getServletMappings() will allow to access root url: “/”. We can override to forward to a different URL.

      当我们访问我们的应用程序时,默认情况下,SpringMVCWebAppInitializer的getServletMappings()将允许访问根URL:“ /”。 我们可以覆盖以转发到其他URL。
    2. The Spring or Pivotal team is working this issue to avoid this much Java code by introduction an annotation. Please check this at https://jira.spring.io/browse/SPR-10359.

      Spring或Pivotal团队正在研究此问题,以通过引入注释来避免这么多Java代码。 请在https://jira.spring.io/browse/SPR-10359上进行检查。
  • Develop welcomePage.jsp file

    开发welcomePage.jsp文件
  • <h3>Welcome to JournalDEV Tutorials</h3>
    <a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>
  • Develop loginPage.jsp file

    开发loginPage.jsp文件
  • <%@ 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

    开发homepage.jsp文件
  • <%@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登录注销示例 (Run Spring Security MVC Login Logout Example)

    To run this Spring Web Application, we need any Web Container which supports Spring 4 and Java 8 Environments With Servlet 3.1.0 Container.

    要运行此Spring Web Application,我们需要任何支持带有Servlet 3.1.0容器的Spring 4和Java 8环境的Web容器。

    • Deploy and Run on Spring TC Server in Spring STS Suite

      在Spring STS Suite中的Spring TC Server上部署和运行
    • It automatically access our application welcome page url as shown below.

      它会自动访问我们的应用程序欢迎页面网址,如下所示。
    • click on “Login to JournalDEV” link to access login page.

      单击“登录到JournalDEV”链接以访问登录页面。
    • Now, provide wrong login details and click on “Login” button.

      现在,提供错误的登录详细信息,然后单击“登录”按钮。
    • Here we can observe this error message: “Invalid Credentials provided.”

      在这里,我们可以观察到以下错误消息:“提供的凭据无效。”

    • Now, provide correct login details configured in “LoginSecurityConfig” class.

      现在,提供在“ LoginSecurityConfig”类中配置的正确登录详细信息。
    • After successful login to our application, we can see our Application Homepage with the “Logout” link.

      成功登录我们的应用程序后,我们可以看到带有“注销”链接的应用程序主页。

    • click on “Logout” link to logout from Application.

      单击“注销”链接以从应用程序注销。
    • Here we can observe that we are Logged out from our application successfully and redirected to Login page again.

      在这里,我们可以观察到我们已成功退出应用程序,并再次重定向到“登录”页面。

      We can observe some Log out successful message in this Login page.

      我们可以在此登录页面中看到一些注销成功的消息。

    NOTE:-
    If we observe this example, we are not using the web.xml file right. As it is a Web Application, Maven searches for web.xml file and raises some errors if it does not find in the application. That’s to avoid Maven related issues, we need to configure “<failOnMissingWebXml>” flag in pom.xml file.

    注意:-
    如果观察此示例,则说明我们没有正确使用web.xml文件。 由于是Web应用程序,因此Maven搜索web.xml文件,如果在应用程序中找不到该文件,则会引发一些错误。 为了避免与Maven相关的问题,我们需要在pom.xml文件中配置“ <failOnMissingWebXml>”标志。

    That’s it all about Spring 4 Security Module Simple Example. We will develop some more real-time useful examples in my coming posts like Managing Roles, Remember-Me Feature, WebSocket Security, and more.

    关于Spring 4 Security Module简单示例的全部内容。 我们将在我的后续文章中开发一些更实时的有用示例,例如“管理角色”,“记住我的功能”,“ WebSocket安全性”等等。

    Please drop me a comment if you like my post or have any issues/suggestions.

    如果您喜欢我的帖子或有任何问题/建议,请给我评论。

    翻译自: https://www.journaldev.com/8718/spring-4-security-mvc-login-logout-example

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值