Para recordar a los usuarios en la computadora mientras inician sesión en un sitio web, a través de Spring Security podemos mantener eso usando la opción «Recordarme». Spring Security envía una cookie al navegador. Esto tendrá un límite de tiempo específico y hasta ese momento la cookie es válida y en ese período de tiempo, para la URL dada, es posible el inicio de sesión automático. Veamos a través de un código de aplicación de muestra para ver la funcionalidad de trabajo.
Proyecto de ejemplo
Spring Security proporciona dos enfoques para implementar recordar-me
- Enfoque de token basado en hash
- Enfoque de token persistente.
En nuestro ejemplo, estamos tomando el enfoque de token persistente en el que se usa una base de datos u otro mecanismo de almacenamiento persistente y es útil almacenar los tokens generados.
Estructura del proyecto:
Este es un proyecto impulsado por maven. Veamos el pom.xml
XML
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.gfg.springsecurity</groupId> <artifactId>spring-security-remember-me-sample-application</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-security-remember-me-sample-application</name> <packaging>war</packaging> <properties> <!-- It is good to use the later versions to get the full supportivity --> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>5.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </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.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> </dependencies> <build> <plugins> <!-- Maven jetty plugin for testing war --> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.8.v20171121</version> </plugin> <!-- To avoid errors, it is mandatory to add this plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> </plugin> </plugins> </build> </project>
En el lado de la base de datos, estamos usando MySQL. Por lo tanto, esas configuraciones se dan en pom.xml. Para probar la aplicación para recordar, necesitamos tener algunas tablas de muestra en la base de datos. Deje que la base de datos de muestra sea ‘geeksforgeeks’. las tablas de muestra son ‘usuarios’ y ‘autoridades’. Para la autenticación ‘recuérdame’, también necesitamos ‘persistent_logins’ para almacenar los tokens generados
use geeksforgeeks; -- users create table users( username varchar(50) not null primary key, password varchar(100) not null, enabled boolean not null ); -- authorities create table authorities( username varchar(50) not null, authority varchar(50) not null, constraint fk_authorities_users foreign key(username) references users(username) ); create unique index ix_auth_username on geekAuthorities (username,authority); create table persistent_logins( username varchar(50) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null );
Insertemos algunos datos en la tabla de usuarios y autoridades con fines de prueba
-- Let us create a user with admin and password as password@123 -- While storing into the database let us store as encoded password with BCryptPasswordEncoder -- For password@123, it will be $2a$10$USD5XrNWIpf2sLnGJ62/v.hTtSIY1vdeF7v8Y4YaNJhTftbX1HBwi insert into users(username,password,enabled) values('admin','$2a$10$hbxecwitQQ.dDT4JOFzQAulNySFwEpaFLw38jda6Td.Y/cOiRzDFu',true); insert into authorities(username,authority) values('admin','ROLE_ADMIN');
Para obtener la contraseña codificada, usando un código de muestra, podemos obtenerla
Java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; //..... BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); // Specify the required password here String password = "password@123"; String encodedPassword = passwordEncoder.encode(password); //---
Ahora vamos a comprobar la información de conectividad de la base de datos. Está disponible en la carpeta src/main/resources
src/main/resources/database.properties
mysql.dirver=com.mysql.jdbc.Driver mysql.jdbcUrl=jdbc:mysql://localhost:3306/geeksforgeeks?serverTimezone=UTC # using geeksforgeeks mysql.username=root # Change the appropriate username here mysql.password=**** # Change the appropriate password here
Comencemos creando la clase @Configuration y dentro de ella definamos el método @Bean para DataSource
ApplicationConfiguration.java
Java
import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; @Configuration @PropertySource("classpath:database.properties") public class ApplicationConfiguration { @Autowired private Environment environment; @Bean public DataSource getDataSource() { BasicDataSource basicDataSource = new BasicDataSource(); basicDataSource.setDriverClassName(environment.getProperty("mysql.dirver")); basicDataSource.setUrl(environment.getProperty("mysql.jdbcUrl")); basicDataSource.setUsername(environment.getProperty("mysql.username")); basicDataSource.setPassword(environment.getProperty("mysql.password")); return basicDataSource; } }
Configuración de Spring Security
- Se necesita la creación de un filtro de servlet springSecurityFilterChain para proteger y validar todas las direcciones URL mediante la creación de una clase @Configuration.
- Necesita registrar el filtro springSecurityFilterChain con war.
- Se requiere el método RememberMe() de la clase HttpSecurity para habilitar la autenticación de recordarme.
- Invoque el método tokenRepository() con el argumento PersistentTokenRepository y almacene los tokens generados en la tabla de la base de datos.
Veamos cómo hacer estos
WebSecurityConfiguration.java
Java
import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; 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.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(dataSource) .usersByUsernameQuery("select username, password, enabled" + " from users where username=?") .authoritiesByUsernameQuery("select username,authority " + "from authorities where username=?") .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().hasAnyRole("ADMIN", "USER") .and() .authorizeRequests().antMatchers("/login**").permitAll() .and() .formLogin().loginPage("/login").loginProcessingUrl("/loginAction").permitAll() .and() .logout().logoutSuccessUrl("/login").permitAll() .and() .rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository()) .and() .csrf().disable(); } @Bean public PersistentTokenRepository tokenRepository() { JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl(); jdbcTokenRepositoryImpl.setDataSource(dataSource); return jdbcTokenRepositoryImpl; } }
SecurityWebApplicationInitializer.java
Java
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { }
La configuración de Spring MVC se realiza mediante el uso de JSP Views para la parte de la vista
WebConfiguration.java
Java
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.gfg.spring.controller" }) public class WebConfiguration implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp().prefix("/WEB-INF/views/").suffix(".jsp"); } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } }
La inicialización y la configuración del contenedor de servlet se pueden ver usando
MvcWebApplicationInitializer.java
Java
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { // Load database and spring security configuration @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { ApplicationConfiguration.class, WebSecurityConfiguration.class }; } // Load spring web configuration @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebConfiguration.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
Veamos ahora la clase de controlador.
SampleController.java
Java
import java.security.Principal; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class SampleContoller { @GetMapping("/") public String index(Model model, Principal principal) { model.addAttribute("message", "Welcome! You are logged by using " + principal.getName() + " username"); return "index"; } }
Veamos ahora la parte de la vista JSP
iniciar sesión.jsp
HTML
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring Security</title> <style> table#sample tr:nth-child(odd) { background-color: #0074ab ; color: yellow ; } table#sample tr:nth-child(even) { background-color: #e6f7ff ; } table#sample { border-collapse: collapse ; } table#sample td { padding: 5px ; } table#sample caption { font-style: italic ; background-color: black ; color: white ; } </style> </head> <body background="#FFFFFF"> <center> <h1>Spring Security - Remember Me Example</h1> <h4>Sample Login Form</h4> <form action='<spring:url value="/loginAction"/>' method="post"> <table id = "sample"> <tr> <td>Username</td> <td><input type="text" name="username"></td> </tr> <tr> <td>Password</td> <td><input type="password" name="password"></td> </tr> <tr> <td><input type="checkbox" name="remember-me"></td> <td>Remember me on this Computer</td> </tr> <tr> <td align="center" colspan="2"><button type="submit">Login</button></td> </tr> </table> </form> <br/> </center> </body> </html>
índice.jsp
HTML
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring Security</title> </head> <body> <h1>Spring Security - Remember Me Example</h1> <h2>${message}</h2> <form action="/logout" method="post"> <input value="Logout" type="submit"> </form> </body> </html>
Como este es el proyecto maven, primero construyamos la aplicación desde el símbolo del sistema de la siguiente manera
mvn clean install
Ejecute la aplicación utilizando
mvn jetty:run
Probemos ahora presionando http://localhost:8080/
admin/password@123 debe proporcionarse como credenciales. Como es el usuario disponible en la tabla de usuarios y esa contraseña se guarda de forma codificada. Como se selecciona la opción recordarme, en la base de datos, podemos ver una entrada en ‘persistent_logins’
Al mismo tiempo, también podemos verificar lo mismo en las cookies. A medida que se usa el navegador Chrome, verifiquemos eso a través de las opciones de configuración del navegador Chrome
A partir de ahora, las credenciales se almacenan en cookies y también en DB debido al mecanismo de persistencia, después de que cerramos el navegador y lo abrimos nuevamente, podemos ver la página de índice cuando presionamos http://localhost:8080 . Esta es la ventaja de la opción Recuérdame. Esto será posible hasta el momento de la expiración. Además, los datos de las cookies no deben borrarse. Aquí para nuestro ejemplo, hasta el 24 de junio, las cookies no se borran, podemos ver la funcionalidad ‘Recordarme’ habilitada.
Publicación traducida automáticamente
Artículo escrito por priyarajtt y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA