12.10.2014

JavaEE: Пример использования Spring Security.

UPDATE: Возможно вам будет интересен пример использования Spring Security 4 и AngularJS.

Spring Security - фреймворк, предоставляющий удобную реализацию механизмов аутентификации и авторизации в Java EE приложениях. Раньше был известен как Acegi Security, а в 2008 году был включен в проект Spring. Является стандартом де-факто для веб-приложений Spring MVC. Использовать Spring Security очень удобно и просто - без особых усилий можно создать гибкую систему управления правами в вашем веб-приложении.

Для того, чтобы показать как это работает - приведу простой, но подробный пример приложения, которое использует Spring Securtiy. Приложение будет состоять из страницы входа и закрытой страницы, доступ к которой имеет только один пользователь. Как нетрудно догадаться, это будет веб-приложение Spring MVC. Итак, цель поставлена, инструменты определены, приступаем к делу!

Для примера создаем шаблонный проект веб-приложения Spring MVC, используя Spring Tool Suite (File > New > Spring Template Project > Spring MVC Project ).

После этого у нас уже есть простое веб-приложение, которое можно запустить на сервере (ссылку на полный код примера можно найти в конце поста). Первое что необходимо сделать - добавить в pom.xml необходимые зависимости:

<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${org.springframework-version}</version>
</dependency>

<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${org.springframework-version}</version>
</dependency>

<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${org.springframework-version}</version>
</dependency>

Потом удалим класс контоллера, и .jsp страницы, которые были автоматически созданы Spring Tool Suite, и добавим свои.  Создадим две .jsp страницы - login.jsp и admin.jsp. Первая - это страница входа, которая в данном случае будет и главной страницей, а вторая - это страница, которая будет доступна только авторизованному пользователю.

login.jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" language="java" %>
<%@ page session="false"%>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Вход</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css" />
<link rel="stylesheet"
	href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
</head>

<body onload='document.f.j_username.focus();'>

	<form name='f' action="<c:url value='/j_spring_security_check' />"
		method='POST'>
		<div class="logincontainer">

			<div class="login">
				<table>
					<tr>
						<td>Имя <input type='text' name='j_username'>
						</td>
					</tr>
					<tr>
						<td>Пароль <input type='password' name='j_password' />
						</td>
					</tr>
				</table>
				<br /> <input class="btn btn-primary" name="submit" type="submit"
					value="Вход" /> <br />
			</div>
			<c:if test="${not empty error}">
				<div class="alert alert-danger" style="width: 285px; margin: 0px auto;" role="alert">
					${error}</div>
			</c:if>
		</div>
	</form>
</body>
</html>

Как видно, здесь есть есть форма для ввода имени пользователя и пароля, для отправки которой указан cпециальный URL j_spring_security_check.

admin.jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
	language="java"%>
<%@ page session="false"%>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Вход</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css" />
<link rel="stylesheet"
	href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
</head>
<body>
	<div id="admin-section">
		<h3>Поздравляем, вы на закрытой странице!</h3>
		<a class="btn btn-primary" href="j_spring_security_logout">Выход</a>
	</div>
</body>
</html>

Здесь аналогично, специальный URL для выхода пользователя из системы j_spring_security_logout. Страницы, которые должны быть закрытыми рекомендуется размещать в отдельной директории, в этом примере страница admin.jsp находится в директории views/private. Теперь необходимо создать файл конфигурации spring-security.xml:

В этом файле во первых указываются правила, согласно которым будет осуществляться доступ к определенным URL. Здесь указываются URL паттерны и роль/роли, которая соответствует этим паттернам:

<http auto-config="true">
	
		<intercept-url pattern="/admin" access="ROLE_ADMIN" />
		<intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
		<intercept-url pattern="/admin*" access="ROLE_ADMIN" />
		
		<form-login login-page="/login" default-target-url="/admin"
		authentication-failure-url="/loginfailed" />
		<logout logout-success-url="/logout" />
		
</http>

Это означает, что перейти по URL, который соответствует одному из указанных паттернов может только пользователь, который соответствует роли ROLE_ADMIN. Ниже в этом файле указана конфигурация и самой роли:

<authentication-manager>
		<authentication-provider>
		<password-encoder hash="sha" />
			<user-service>
				 <user name="admin" password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
				 authorities="ROLE_ADMIN" />
			</user-service>
		</authentication-provider>
</authentication-manager>

В данном случае, таким образом задан один пользователь admin, с паролем 123. Пароли по известным соображениям не должны храниться в открытом виде, поэтому здесь указывается хеш код пароля SHA1. Теперь нужно добавить добавить spring-security.xml в web.xml:

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		/WEB-INF/spring/root-context.xml
		/WEB-INF/spring/spring-security.xml
		</param-value>
</context-param>

Таже в web.xml нужно добавить фильтр для включения 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>

Осталось создать классы контроллеров. Создадим два отдельных класса, один для страницы входа (LoginController.java), другой - для закрытой страницы (AdminController.java). В LoginConroller.java добавлен маппинг для перехода по URL “/” так как домашней страницей в нашем примере является страница входа.

LoginController:

@Controller
public class LoginController {
	
	private final String ERROR_MESSAGE = "Неправильные имя/пароль";
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home() {
		return "login";
	}
	
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login() {
		return "login";
	}

	@RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
	public String loginerror(ModelMap model) {
		model.addAttribute("error", ERROR_MESSAGE);
		return "login";
	}

	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String logout() {
		return "login";
	}
	
}

AdminController:

@Controller
public class AdminController {
	
	@RequestMapping(value = "/admin", method = RequestMethod.GET)
	public String home() {
		return "private/admin";
	}
}

Запустим приложение на Java EE сервере или в контейнере сервлетов (например Apache Tomcat):

Перенаправление на страницу входа осуществляется при переходе на целевую страницу, а также с домашней страницы. Неправильный ввод пароля/имени пользователя даст такой результат:

А в случае успеха мы попадаем на целевую закрытую страницу:

Мы рассмотрели элементарный пример использования Spring Securtiy. Как видно, использовать его достаточно просто и удобно. Нет никакой необходимости беспокоиться о сессиях и прочих деталях - достаточно указать соответствующие правила для пользователей в конфигурации, а о всем остальном позаботится фреймворк.

GIT

Скачать пример



Теги: programming Spring javaEE

comments powered by Disqus