Сегодня мы узнаем о Примере входа в систему Spring Security. Прежде чем читать этот пост, пожалуйста, ознакомьтесь с моим предыдущим постом по ссылке “Введение в Spring 4 Security”, чтобы получить некоторые основы.
Пример входа и выхода Spring Security
В этом посте мы собираемся разработать веб-приложение Spring 4 MVC Security для предоставления возможности входа и выхода, используя опцию In-Memory. В этом примере используются конфигурация Java Spring с использованием аннотаций Spring, что означает отсутствие использования web.xml и конфигурации Spring XML (старый стиль). Если вы не знакомы с модулем безопасности Spring 3.x, ознакомьтесь с следующими постами, чтобы познакомиться с рецептом Spring Security.
- Пример безопасности Spring MVC с использованием в памяти, UserDetailsService и аутентификации JDBC
- Безопасность Spring в веб-приложении с использованием DAO, JDBC, аутентификации в памяти
Модуль безопасности Spring 4 поддерживает следующие варианты для хранения и управления учетными данными пользователя:
- Хранение в памяти
- Реляционные базы данных (СУБД)
- NoSQL хранилища данных
- 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 Beans. Это означает, что мы собираемся использовать функцию конфигурации Spring Java с аннотациями Spring. Мы разработаем это приложение со следующими функциями:
- Страница приветствия
- Страница входа
- Домашняя страница
- Функция выхода
Используйте следующие шаги для разработки и изучения этого простого примера входа в систему Spring 4 Security.
- Создайте проект “Простой веб-проект Spring 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>
ПРИМЕЧАНИЕ:- Если вы не знакомы с флагом “<failOnMissingWebXml>”, пожалуйста, прочтите в конце этого сообщения, чтобы получить хорошее представление об использовании этого элемента. – Во-первых, разработайте контроллер входа, используя аннотацию @Controller.
Controller.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;
}
}
Объяснение кода:- Мы определили три метода в “LoginController” для обработки трех различных типов запросов клиентов
- welcomePage() будет обрабатывать все запросы клиентов, которые используют URI “/”
- homePage() будет обрабатывать все запросы клиентов, которые используют URI “/homePage”
- loginPage() будет обрабатывать все запросы клиентов, которые используют URI “/loginPage”
- В 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” для хранения и управления учетными данными пользователей и обеспечения функций безопасности входа и выхода.
- @EnableWebSecurity Аннотация используется для включения веб-безопасности в любом веб-приложении.
- @EnableWebMVCSecurity Аннотация используется для включения веб-безопасности в веб-приложении на основе Spring MVC.
ПРИМЕЧАНИЕ:- @EnableWebSecurity = @EnableWebMVCSecurity + Дополнительные функции. Вот почему аннотация @EnableWebMVCSecurity устарела в Spring 4.x Framework.4. Класс “LoginSecurityConfig” или любой другой класс, который предназначен для настройки Spring Security, должен расширять класс “WebSecurityConfigurerAdapter” или реализовывать соответствующий интерфейс. - Метод configureGlobal() используется для хранения и управления учетными данными пользователя.
- В методе configureGlobal() мы можем использовать метод authorities() для определения ролей нашего приложения, например, “ROLE_USER”. Мы также можем использовать метод roles() для этой же цели.
- Разница между методами authorities() и roles():
- Метод authorities() требует полного имени роли, например, “ROLE_USER”, а метод roles() требует имени роли, например, “USER”. Он автоматически добавит значение “ROLE_” к имени роли “USER”. ПРИМЕЧАНИЕ:- Мы разработаем другой пример, чтобы продемонстрировать роли, такие как “USER”, “ADMIN”, в моих будущих сообщениях.
- Важный метод для обеспечения безопасности входа и выхода – configure(HttpSecurity http)
- Следующий фрагмент кода используется для предотвращения несанкционированного доступа к “/homePage”. Если вы попытаетесь получить доступ к этой странице напрямую, мы будем автоматически перенаправлены на страницу “/loginPage”.
.antMatchers("/homePage").access("hasRole('ROLE_USER')")
Если мы удалим вызов метода access(“hasRole(‘ROLE_USER’)”), то мы сможем получить доступ к этой странице без входа в наше приложение. Мы настроили функции входа и выхода, используя методы 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, чтобы избежать написания файла “web.xml”.
- @EnableWebMvc Аннотация используется для включения функций приложения Spring Web MVC в Spring Framework
- @Import Аннотация используется для импорта класса конфигурации Spring Security в этот класс.
- @ComponentScan Аннотация используется для сканирования компонентов в указанном пакете. Она эквивалентна “context:component-scan” в конфигурации Spring XML.
- Инициализация Spring Security
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 “SpringMVCWebAppInitializer” класс используется для инициализации “DispatcherServlet” без файла web.xml в конфигурации на основе аннотаций. 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[] { "/" };
}
}
ПРИМЕЧАНИЕ:-
- Когда мы получаем доступ к нашему приложению, по умолчанию метод getServletMappings() класса SpringMVCWebAppInitializer позволит получить доступ к корневому URL: “/”. Мы можем переопределить его для перенаправления на другой URL.
- Команда 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 Login Logout
Для запуска этого веб-приложения Spring нам нужен любой веб-контейнер, который поддерживает среды Spring 4 и Java 8 с Servlet 3.1.0.
- Развернуть и запустить на Spring TC Server в Spring STS Suite
- Он автоматически получает доступ к URL нашей страницы приветствия приложения, как показано ниже.
– щелкните по ссылке “Вход в JournalDEV”, чтобы перейти на страницу входа.
– Теперь введите неправильные данные для входа и нажмите кнопку “Вход”.
Здесь мы можем видеть сообщение об ошибке: “Предоставлены недопустимые учетные данные”.- Теперь введите правильные данные для входа, настроенные в классе “LoginSecurityConfig”.
После успешного входа в наше приложение мы видим домашнюю страницу приложения с ссылкой “Выход”.- нажмите на ссылку “Выход”, чтобы выйти из приложения.
Здесь мы можем видеть, что мы успешно вышли из нашего приложения и снова перешли на страницу входа. Мы можем видеть некоторое сообщение об успешном выходе на этой странице входа.
Примечание:- Если мы рассмотрим этот пример, мы не используем файл web.xml правильно. Поскольку это веб-приложение, Maven ищет файл web.xml и выдает ошибки, если не находит его в приложении. Чтобы избежать проблем с Maven, нам нужно настроить флаг “failOnMissingWebXml” в файле pom.xml. Вот и все, что касается простого примера Spring 4 Security Module. Мы разработаем еще несколько реальных полезных примеров в моих будущих сообщениях, таких как управление ролями, функция Remember-Me, безопасность WebSocket и другие. Пожалуйста, оставьте комментарий, если вам понравилась моя публикация или у вас есть какие-либо проблемы/предложения.
Source:
https://www.digitalocean.com/community/tutorials/spring-4-security-mvc-login-logout-example