Пример авторизации с доступом на основе ролей в Spring Security

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

Роль Spring Security

В этом посте мы обсудим, как определить, использовать и управлять ролями Spring Security, такими как “USER”, “ADMIN” в веб-приложении Spring. Как и в моем предыдущем посте, в этом примере также используется Spring 4 MVC Security с In-Memory Store и функцией конфигурации Spring Java для разработки приложения. Это означает, что мы не собираемся использовать файл web.xml, а также не будем писать ни одной строки конфигурации Spring XML. Мы будем использовать опцию “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

  1. Создайте проект “Simple Spring Web Maven” в Spring STS Suite с указанными деталями.
    Имя проекта: SpringMVCSecruityMavenRolesApp2. Используйте тот же файл pom.xml из моего предыдущего сообщения с следующими изменениями
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>

<build>
  <finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
  1. . Используйте все файлы Java и JSP из моего предыдущего сообщения. Здесь мы будем обсуждать только обновленное или новое содержимое
  2. .

    Обновите файл LoginSecurityConfig.java для настройки ролей пользователя, таких как “USER” и “ADMIN”.
    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("jduser").password("jdu@123").authorities("ROLE_USER")
			.and()
			.withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {

		
		http.authorizeRequests()
			.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
			.antMatchers("/userPage").access("hasRole('ROLE_USER')")
			.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
			.and()
				.formLogin().loginPage("/loginPage")
				.defaultSuccessUrl("/homePage")
				.failureUrl("/loginPage?error")
				.usernameParameter("username").passwordParameter("password")				
			.and()
				.logout().logoutSuccessUrl("/loginPage?logout"); 
		
	}
}

Объяснение кода

  1. В методе configureGlobal() мы добавили двух пользователей: одного с ролью “ROLE_USER” и другого с ролями “ROLE_USER” и “ROLE_ADMIN”. Это означает, что этот второй пользователь будет выступать в роли администратора. Таким образом, мы можем настроить любое количество пользователей и ролей.
  2. Мы можем использовать методы authorities(ROLE) или roles(ROLE) для настройки ролей в нашем приложении.
  3. Разница между методами authorities() и roles():
  • Метод authorities() требует полное имя роли, например, “ROLE_USER”.
  • Метод roles() требует имени роли, например, “USER”. Он автоматически добавляет значение “ROLE_” к этому имени роли “USER”.
  1. В методе configure() мы определили различные URL с требуемыми ролями доступа.
antMatchers("/homePage")
   .access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")

Этот фрагмент кода настраивает доступность “/homePage” для ролей USER и ADMIN.

 .antMatchers("/userPage").access("hasRole('ROLE_USER')")
 .antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")

Этот фрагмент кода настраивает доступность “/userPage” только для роли USER и “/adminPage” только для роли ADMIN. Если другие роли пытаются получить доступ к этим страницам, мы получим сообщение об ошибке “403 Доступ запрещен”.

  1. Обновите файл контроллера LoginController.java, чтобы определить новые пути доступа к URL, как показано ниже.
    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 = {"/userPage"}, method = RequestMethod.GET)
	public ModelAndView userPage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("userPage");
		return model;
	}
	
	@RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET)
	public ModelAndView adminPage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("adminPage");
		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;
	}

}

Объяснение кода Кроме предыдущего примера, здесь мы добавили два новых URL-адреса.

  1. “/userPage” используется ролью ПОЛЬЗОВАТЕЛЯ для доступа и выполнения обычных пользовательских действий.

  2. “/adminPage” используется ролью АДМИНИСТРАТОРА для доступа и выполнения административных действий. Роль АДМИНИСТРАТОРА также может получить доступ к URL “/userPage”.

  3. Обновлен файл homePage.jsp для предоставления специфических для ролей ПОЛЬЗОВАТЕЛЯ и АДМИНИСТРАТОРА действий.
    homePage.jsp

<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Logout</a>

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

Здесь мы добавляем три варианта меню в верхнем фрейме. “Выход” уже обсуждался в моем предыдущем сообщении. Новые две ссылки:

  1. JD Пользователь: Доступно как для ролей “ПОЛЬЗОВАТЕЛЯ”, так и для ролей “АДМИНИСТРАТОРА”
  2. JD Администратор: Доступен только для ролей “АДМИНИСТРАТОРА”

ПРИМЕЧАНИЕ:- В реальных приложениях мы будем показывать только ссылку “JD Пользователь” для роли “ПОЛЬЗОВАТЕЛЯ” и скрывать ссылку “JD Администратор”. Чтобы проверить, доступна ли она для роли “ПОЛЬЗОВАТЕЛЯ”, или нет, и также увидеть точное сообщение об ошибке, мы не скрывали эту ссылку.Добавьте новый файл adminPage.jsp, чтобы он действовал как домашняя страница для роли “АДМИНИСТРАТОР”.

<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>Admin Page</h3>

<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>
  1. Добавьте новый файл userPage.jsp для использования в качестве домашней страницы для роли “USER”.
    userPage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>User Page</h3>

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

Мы завершили разработку нашего приложения. Пришло время посмотреть на окончательную структуру проекта и протестировать приложение.26. Окончательная структура проекта выглядит следующим образом:

Пример приложения Spring Security Roles Test

  1. Щелкните правой кнопкой мыши на проекте в среде разработки Spring STS IDE и выберите опцию “Запустить как >> Запустить на сервере”. Это откроет стандартную приветственную страницу приложения, как показано ниже: 3. Нажмите на ссылку “Войти в JournalDEV”. Теперь вы находитесь на странице входа.
    5. Сначала войдите с учетными данными роли “ПОЛЬЗОВАТЕЛЬ”:
    Имя пользователя: jduser Пароль: jdu@123 Теперь мы увидим домашнюю страницу приложения с 3 вариантами меню: “JD Пользователь”, “JD Администратор” и “Выход”. Нажмите на ссылку “JD Пользователь”. Поскольку мы вошли в приложение, используя учетные данные роли “ПОЛЬЗОВАТЕЛЬ”, мы можем получить доступ к этой ссылке, как показано ниже. Просто используйте кнопку “назад” в среде разработки Spring STS и на этот раз нажмите на ссылку “JD Администратор”. Поскольку мы вошли с учетными данными роли “ПОЛЬЗОВАТЕЛЬ”, мы не можем получить доступ к этой ссылке. Вот почему мы видели это сообщение об ошибке: “403 Доступ запрещен”. 9. Теперь вы вышли из системы, и снова войдите с учетными данными роли “АДМИНИСТРАТОР”:
    Имя пользователя: jdadmin Пароль: jda@123 На этот раз мы можем успешно получить доступ к ссылке “JD Администратор”, как показано ниже. Проверьте ссылку “Выход”, чтобы выйти из приложения.

Всё дело в примере ролей Spring Security для предоставления авторизованного доступа к страницам веб-приложения.

Source:
https://www.digitalocean.com/community/tutorials/spring-security-role-based-access-authorization-example