Ejemplo de Autorización de Acceso Basada en Roles con Spring Security

Hoy vamos a analizar el ejemplo de acceso y autorización basado en roles de Spring Security. Sin embargo, antes de leer esta publicación, por favor revisa mi publicación anterior sobre “Ejemplo de inicio y cierre de sesión de Spring 4 Security MVC” para obtener algunos conocimientos básicos sobre Spring 4 Security.

Rol de Spring Security

En esta publicación, discutiremos cómo definir, usar y gestionar roles de seguridad de Spring como “USER”, “ADMIN” en una aplicación web de Spring. Al igual que en mi publicación anterior, este ejemplo también utiliza Spring 4 MVC Security con In-Memory Store y la característica de configuración Java de Spring para desarrollar la aplicación. Esto significa que no vamos a usar el archivo web.xml y tampoco escribiremos ni una sola línea de configuración XML de Spring. Utilizaremos la opción “In-Memory Store” para almacenar y gestionar las credenciales de usuario. Vamos a utilizar Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 con Java 1.8 y la herramienta de construcción Maven para desarrollar este ejemplo.

Ejemplo de Autorización de Acceso Basado en Roles de Spring Security

  1. Cree un proyecto “Simple Spring Web Maven” en Spring STS Suite con los siguientes detalles.
    Nombre del Proyecto: SpringMVCSecruityMavenRolesApp2. Utilice el mismo archivo pom.xml de mi publicación anterior con los siguientes cambios
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>

<build>
  <finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
  1. Utilice todos los archivos Java y JSP de mi publicación anterior. Discutiremos solo el contenido actualizado o recién agregado aquí.
  2. Actualice el archivo LoginSecurityConfig.java para configurar roles de usuario como “USER” y “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"); 
		
	}
}

Explicación del Código

  1. En el método configureGlobal(), hemos agregado dos usuarios: Un usuario con el rol “ROLE_USER” y otro usuario con los roles “ROLE_USER” y “ROLE_ADMIN”. Esto significa que este segundo usuario actuará como usuario administrador. De esta manera, podemos configurar cualquier número de usuarios y roles.
  2. Podemos usar tanto el método authorities(ROLE) como el método roles(ROLE) para configurar roles en nuestra aplicación.
  3. Diferencia entre los métodos authorities() y roles():
  • authorities() necesita el nombre completo del rol como “ROLE_USER”
  • roles() necesita el nombre del rol como “USER”. Agregará automáticamente el valor “ROLE_” a este nombre de rol “USER”.
  1. En el método configure(), hemos definido diferentes URL con roles de acceso requeridos.
antMatchers("/homePage")
   .access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")

Este fragmento de código configura que “/homePage” está disponible para ambos roles de USER y ADMIN.

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

Este fragmento de código configura que “/userPage” es accesible solo por el rol “USER” y “/adminPage” es accesible solo por el rol “ADMIN”. Si otros roles intentan acceder a estas páginas, recibiremos el mensaje de error “403 Access is Denied”.

  1. Actualice el archivo Controlador LoginController.java para definir nuevos caminos de acceso URL como se muestra a continuación.
    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;
	}

}

Explicación del código Además del ejemplo anterior, aquí hemos agregado dos URLs nuevas más.

  1. “/userPage” es utilizado por el Rol USUARIO para acceder y realizar actividades de usuario normales.

  2. “/adminPage” es utilizado por el Rol ADMIN para acceder y realizar actividades de usuario administrador. El rol ADMIN también puede acceder a la URL “/userPage”.

  3. Se actualizó el archivo homePage.jsp para proporcionar actividades específicas para los Roles de Usuario y Administrador.
    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>

Aquí hemos agregado tres opciones de menú en la parte superior. “Cerrar sesión” ya se discutió en mi publicación anterior. Los dos nuevos enlaces son:

  1. JD Usuario: Accesible por los Roles “USUARIO” y “ADMIN”
  2. JD Administrador: Accesible solo por los Roles “ADMIN”

NOTA:- En aplicaciones en tiempo real, mostraremos solo el enlace “JD Usuario” al Rol “USUARIO” y ocultaremos el enlace “JD Administrador”. Para probar si es accesible por el Rol “USUARIO” o no y también para ver el mensaje de error exacto, no hemos ocultado este enlace.Se agregó un nuevo archivo adminPage.jsp para actuar como una página de inicio para el Rol “ADMIN”.

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

¡Agrega un nuevo archivo userPage.jsp para que actúe como página de inicio para el rol “USER”!

Prueba de la aplicación de ejemplo con roles de seguridad de Spring

  1. Haz clic derecho en el proyecto en el entorno de desarrollo integrado Spring STS y selecciona la opción “Ejecutar como >> Ejecutar en servidor”. Accederá a la página de bienvenida de la aplicación por defecto como se muestra a continuación: 3. Haz clic en el enlace “Iniciar sesión en JournalDEV”. Ahora estás en la página de inicio de sesión. 5. Primero inicia sesión con las credenciales de rol “USER”: Nombre de usuario: jduser Contraseña: jdu@123 Ahora veremos la página de inicio de la aplicación con 3 opciones de menú: “Usuario JD”, “Administrador JD” y “Cerrar sesión”. Haz clic en el enlace “Usuario JD”. Como hemos iniciado sesión en la aplicación usando las credenciales de rol “USER”, podemos acceder a este enlace como se muestra a continuación. Simplemente usa la flecha hacia atrás en Spring STS IDE y esta vez haz clic en el enlace “Administrador JD”. Como hemos iniciado sesión con las credenciales de rol “USER”, no podemos acceder a este enlace. Por eso vimos este mensaje de error: “403 Acceso denegado”.9. Ahora cierra sesión y vuelve a iniciar sesión con las credenciales de rol “ADMIN” Nombre de usuario: jdadmin Contraseña: jda@123 Esta vez podemos acceder al enlace “Administrador JD” correctamente como se muestra a continuación. Prueba el enlace “Cerrar sesión” para salir de la aplicación.

Eso es todo sobre el ejemplo de roles de seguridad de Spring para proporcionar acceso autorizado a las páginas de la aplicación web.

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