La necesidad de usar Spring Security Annotation y eliminar los XML esta creciendo . La mayoría de nosotros usamos Spring 4.X a la espera del salto que depare la versión 5 con flux etc. Sin embargo a veces es difícil encontrar documentación clara de como configurar el framework a nivel de seguridad utilizando anotaciones y eliminando los XML. Vamos a ver como podemos hacerlo y cuales son los pasos a seguir. Lo primero que deberemos hacer es configurar las dependencias de Maven necesarias.
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.2.3.RELEASE</version> </dependency> </dependencies>
Spring Security Annotation
El segundo paso es crear un WebInitializer. ¿Qué es un un WebInitializer? . Se trata de una clase que se ejecuta al arrancar nuestra aplicación web y puede abordar tareas adicionales que la aplicación necesita como por ejemplo registrar Servlets o Filtros. Veamos su código:
package com.arquitecturajava.inicializador; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.DispatcherServlet; import com.arquitecturajava.SpringConfiguracion; public class SpringInicializador implements WebApplicationInitializer{ public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringConfiguracion.class); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain")) .addMappingForUrlPatterns(null, false, "/*"); } }
El WebInitializer , se encarga de registrar el dispatcher Servlet de Spring Framework que es el que hace el rol de FrontController y el DelegatingFilterProxy que es el filtro que habilita Spring Security en nuestra aplicación.
Una vez registrados el filtro protege el acceso al DispatcherServlet y por consecuencia al resto de la aplicación.
Una vez tenemos estos pasos realizados el siguiente paso es crear un controlador que tenga un par de urls de acceso.
package com.arquitecturajava.controllers; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ControladorHola { @RequestMapping("/hola") public String hola(ModelMap model) { model.addAttribute("mensaje", "hola desde spring mvc"); return "hola"; } @RequestMapping("/adios") public String adios(ModelMap model) { model.addAttribute("mensaje", "adios desde spring mvc"); return "adios"; } }
Hecho esto nos queda crear un fichero de configuración de Spring que registre un ViewResolver y de de alta nuestro controlador a través de la anotación component scan.
package com.arquitecturajava; 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.ViewResolver; 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.arquitecturajava.*") @Import({SpringConfiguracionSeguridad.class}) public class SpringConfiguracion { @Bean public ViewResolver viewResolver() { System.out.println("llega"); InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/vistas/"); viewResolver.setSuffix(".jsp"); return viewResolver; } }
El siguiente paso es construir los ficheros JSP que van a ser nuestras vistas(ambos ficheros son iguales):
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${mensaje } </body> </html>
Nos queda de configurar el fichero concreto de Spring Security Annotation (SpringConfiguracionSeguridad.class) , que es el encargado de definir las url protegidas de acceso y el cual tenemos referenciado desde el fichero de configuración principal con @import.
package com.arquitecturajava; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; 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; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @EnableWebSecurity public class SpringConfiguracionSeguridad extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/**").hasRole("BASICO").and().formLogin(); super.configure(http); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("cecilio").password("miclave").roles("BASICO"); } }
En este caso protegemos la aplicación completa y únicamente registramos un usuario con rol básico en memoria para comprobar el acceso. Es momento de solicitar una de las dos páginas configuradas en el navegador http://localhost:8080/springsecurity/hola . Una vez solicitada la url , seremos redireccionados al login de la aplicación con el formulario por defecto de Spring Security.
Introducimos el nombre y la clave del usuario y accederemos al recurso solicitado.
Acabamos de configurar Spring 4 y Spring Security usando anotaciones.
Otros artículos relacionados:
cuando intento entrar a una url y ya se ha terminado sesión, entonces me redirige al login. Ej: localhost:8080/MyApp/catalogo …. localhost:8080/MyApp/login (HASTA AQUI SIN NINGUN PROBLEMA), pero cuando mi Apache Tomcat lo configuro al 443, entonces cuando me redirecciona, le quita al puerto, EJ = localhost/MyApp/login …. OBVIAMENTE, MARCA UN ERROR, … yo le tengo que poner manualmente el puerto. ¿¿¿QUE PODRA SER?? ¿¿¿PORQUE SOLO HACE ESO CUANDO CAMBIO DE PUERTO????
DE ANTE MANO GRACIAS!
Otra cosa que me percate, es solo en las URL que tienen ACCESO RESTRINGIDO, en las paginas que estan como PermiAll, no hace eso …
new String[]{“/”, “/home”})).access(“permitAll”).antMatchers(
new String[]{“/initComplaint”})).access(“hasRole(‘QCADMIN’) or hasRole(‘PROATENTION’) “).antMatchers(
new String[]{“/monthlyReport”})).access(“hasRole(‘QCADMIN’) “).antMatchers(
Buenas Cecilio, la verdad he seguido mucho tu blog para sacarme dudas hasta he leido 2 libros tuyos.
La pregunta que te hago es que no quiero trabajar con Spring MVC porque el grupo de trabajo no sabe usarlo y quiero que cuando la aplicación web esté finalizada darle seguridad con Spring Security.
Se puede hacer? Puede dar un ejemplo?
Gracias
En principio podrías hacerlo pero para ello necesitarias dar de alta el filtro de spring security en el web.xml y luego securizar las urls con la configuración que consideres. Ademas sería importante anotar las acciones o cosas similares que tengas con @Component para poder hacer una gestión mas a detalle. Pero no me ha tocado nunca te soy franco
Gracias por el artículo! Una pregunta como se haría para agregar más usuarios/ admin? Y es posible implementar este código a un código que ya tiene una parte del código hecho?
es muy versatil se pueden hacer muchas cosas , por ejemplo se pueden tener varios providers de seguridad combinados , pero es probable que en tu caso necesites un custom provider
es necesario eliminar el web.xml para poder trabajar con las anotaciones
no es obligatorio
Hola, espero que esté bien, interesante blog, tengo ciertas dudas sobre spring security que quizá usted me pueda ayudar a resolver. Vengo del mundo php, y uso principalmente Laravel, en laravel hay una manera de crear una seguridad como esa con “php artisan make:auth”, lo cual crea todas las rutas y formularios de register, login, logout y sus respectivos redirects. Solo resta que uno haga las modificaciones propias si el proyecto lo amerita. Quería saber si 1 – ¿Es lo mismo que hace spring security: formularios y rutas de login, logout y register? Además cuando estaba empezando a estudiar spring… Read more »
Si en principio todo lo que dices es abordable con Spring Security , es un framework orientado a la seguridad y aporta una gran flexibilidad, no me conozco laravel tan a detalle pero pienso que Spring Security es más flexible. Al estar especializado en seguridad
Muy buena explicación!!!
gracias 🙂
Gracias, muy instructivo
de nada 🙂