Поиск по сайту:

Spring 4 Security MVC Пример входа в систему и выхода из системы


Сегодня мы узнаем о примере входа в Spring Security. Прежде чем читать этот пост, просмотрите мой предыдущий пост «Введение в безопасность Spring 4», чтобы получить некоторые основы.

Пример выхода из Spring Security

В этом посте мы собираемся разработать веб-приложение Spring 4 MVC Security, чтобы обеспечить функции входа и выхода с использованием параметра In-Memory. В этом примере используется Spring Java Config с Spring Annotations, то есть без использования web.xml и Spring XML Configuration (старый стиль). Если вы не знакомы с модулем безопасности Spring 3.x, сначала просмотрите следующие сообщения, чтобы попробовать рецепт безопасности Spring.

  1. Пример безопасности Spring MVC с использованием in-memory, UserDetailsService и аутентификации JDBC
  2. Spring Security в веб-приложении сервлетов с использованием DAO, JDBC, аутентификации в памяти

Spring 4 Security Module поддерживает следующие параметры для хранения учетных данных пользователя и управления ими:

  1. Магазин в памяти
  2. Базы данных отношений (RDBMS)
  3. Нет хранилищ данных SQL
  4. LDAP

В этом примере мы будем использовать опцию «In-Memory Store». Другие варианты мы обсудим в моих следующих сообщениях. Мы собираемся использовать 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 Beans. Это означает, что мы собираемся использовать функцию Spring Java Config с Spring Annotations. Мы разработаем это приложение со следующими функциями:

  1. Страница приветствия
  2. Страница входа
  3. Главная страница
  4. Функция выхода

Пожалуйста, используйте следующие шаги для разработки и изучения этого примера простого входа в Spring 4 Security.

  • Создайте проект «Simple Spring Web Maven» в Spring STS Suite, указав следующие сведения.

   Project Name : SpringMVCSecruityMavenApp

  • Добавить в файл 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>

ПРИМЕЧАНИЕ: - Если вы не знаете о флаге \, прочитайте в конце этого поста, чтобы получить хорошее представление об использовании этого элемента. - Во-первых, разработайте контроллер входа в систему, используя аннотацию Spring @Controller.

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;
	}

}

Объяснение кода: — Мы определили три метода в «LoginController» для обработки трех различных типов клиентских запросов.

  1. welcomePage() будет обрабатывать все клиентские запросы, использующие URI \/.
  2. homePage() будет обрабатывать все клиентские запросы, использующие URI \/homePage.
  3. loginPage() будет обрабатывать все клиентские запросы, использующие URI \/loginPage.
  4. В функции loginPage() мы позаботились об обработке сообщений об ошибках и выходе из системы.

  • Затем разработайте класс \LoginSecurityConfig, чтобы обеспечить функции безопасности входа и выхода с помощью Spring 4 Security API. 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"); 
		
	}
}

Объяснение кода: — Мы определили два метода в «LoginSecurityConfig» для хранения учетных данных пользователя и управления ими, а также для обеспечения безопасности входа и выхода из системы.

  1. Аннотация @EnableWebSecurity используется для включения веб-безопасности в любом веб-приложении.
  2. Аннотация @EnableWebMVCSecurity используется для включения веб-безопасности в веб-приложении на основе Spring MVC. ПРИМЕЧАНИЕ. - Аннотация @EnableWebMVCSecurity устарела в Spring 4.x Framework.4. Класс \LoginSecurityConfig или любой другой класс, предназначенный для настройки Spring Security, должен расширять класс \WebSecurityConfigurerAdapter или реализовывать соответствующий интерфейс.
  3. Метод configureGlobal() используется для хранения учетных данных пользователя и управления ими.
  4. В методе configureGlobal() мы можем использовать метод author() для определения ролей нашего приложения, например \ROLE_USER. Мы также можем использовать метод roles() для той же цели.
  5. Разница между методами author() и roles():
  6. authorities() требует полного имени роли, например \ROLE_USER. Он автоматически добавит значение \ROLE_ к этому имени роли \USER. ПРИМЕЧАНИЕ. Мы разработаем еще один пример для демонстрации таких ролей, как \ПОЛЬЗОВАТЕЛЬ,\АДМИН в моих следующих сообщениях.
  7. Важным методом обеспечения безопасности входа и выхода является настройка (HttpSecurity http)
  8. Следующий фрагмент кода используется для предотвращения несанкционированного доступа к \/homePage. Если вы попытаетесь получить доступ к этой странице напрямую, мы будем автоматически перенаправлены на страницу \/loginPage.

.antMatchers("/homePage").access("hasRole('ROLE_USER')")

Если мы удалим вызов метода access(\hasRole('ROLE_USER')), то мы сможем получить доступ к этой странице без входа в наше приложение. 13. Мы настроили функции входа и выхода с помощью методов formLogin() и logout().

  • Включить конфигурацию Spring MVC 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;
	}
	
}

Объяснение кода: — Мы используем класс «LoginApplicationConfig» для определения преобразователей Spring MVC View, чтобы избежать записи файла «web.xml».

  1. Аннотация @EnableWebMvc используется для включения функций приложения Spring Web MVC в Spring Framework
  2. Аннотация @Import используется для импорта класса Spring Security Configuration в этот класс.
  3. context:component-scan» в Spring XML Configuration.

  • Инициализировать безопасность Spring

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

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

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

«SpringSecurityInitializer» используется для регистрации DelegatingFilterProxy для использования springSecurityFilterChain. Это позволяет избежать записи конфигурации фильтров в файл web.xml. — Инициализация приложения Spring MVC

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[] { "/" };
	}
	
}

ПРИМЕЧАНИЕ:-

  1. Когда мы получаем доступ к нашему приложению, по умолчанию getServletMappings() SpringMVCWebAppInitializer позволяет получить доступ к корневому URL-адресу: \/. Мы можем переопределить переадресацию на другой URL-адрес.
  2. Команда Spring или Pivotal работает над этой проблемой, чтобы избежать большого количества кода Java путем введения аннотаций. Пожалуйста, проверьте это на странице https://jira.spring.io/browse/SPR-10359.

  • Разработать файл welcomePage.jsp

<h3>Welcome to JournalDEV Tutorials</h3>
<a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>

  • Разработать файл 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>

  • Разработать файл 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>

Пример запуска Spring Security MVC для входа в систему

Чтобы запустить это веб-приложение Spring, нам нужен любой веб-контейнер, который поддерживает среды Spring 4 и Java 8 с контейнером Servlet 3.1.0.

ПРИМЕЧАНИЕ. Если мы наблюдаем этот пример, мы неправильно используем файл web.xml. Поскольку это веб-приложение, Maven ищет файл web.xml и выдает некоторые ошибки, если не находит его в приложении. Чтобы избежать проблем, связанных с Maven, нам нужно настроить флаг \ в файле pom.xml. Вот и все о простом примере модуля безопасности Spring 4. Мы разработаем еще несколько полезных примеров в реальном времени в моих следующих сообщениях, таких как Управление ролями, функция «Запомнить меня», безопасность WebSocket и т. д. Пожалуйста, напишите мне комментарий, если вам понравился мой пост или у вас есть какие-либо вопросы/предложения.