java - puede - spring mvc ejemplo
Ejemplo de formulario de inicio de sesión Spring (6)
Traté de buscar en Google, pero no pude encontrar ningún buen ejemplo en el que se verificaran un nombre de usuario y una contraseña con una base de datos con fines de autenticación.
En palabras más simples, ¿cómo puedo crear un formulario de inicio de sesión simple usando Spring e Hibernate donde las credenciales se verifican con la base de datos?
Actualizar
¿Alguien ha encontrado un ejemplo simple en el que pueda ver cómo va el flujo y cómo se pasan los datos de entrada para hibernar?
App-fusible le dará un ejemplo completo de trabajo: http://appfuse.org/display/APF/AppFuse+QuickStart
O si tiene maven instalado simplemente ejecute:
mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-light-spring-security-archetype -DarchetypeVersion=2.1.0-M2 -DgroupId=com.mycompany -DartifactId=myproject
Esto generará un proyecto de luz de aplicaciones con mvc de muelles, seguridad de muelles e hibernación.
El siguiente enlace le dará exactamente lo que está buscando. Hay una página de inicio de sesión que acepta ID de usuario y contraseña. La contraseña se almacena en texto plano, ya que es solo un proyecto de prueba. La base de datos utilizada es MySQL. Puede consultar los pasos, descargar el código y el archivo war del siguiente enlace. Avíseme si tiene problemas para ejecutar la aplicación. ¡Espero eso ayude! http://badalchowdhary.wordpress.com/2012/02/26/spring-hibernate-integration/
La configuración básica de xml se puede ver en la publicación de "Ángulo fácil". La parte que mencionó como "myUserService" es un bean que implementa "UserDetailService". Ese tiene básicamente un solo método para implementar, que es el siguiente
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException
Si usa Spring, entonces probablemente tendrá un Bean, que maneja el acceso a su User-Table. Ese solo puede insertar en esa clase para recuperar los detalles del usuario, como:
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
UserTable user = userbean.getUserbyName(name);
if (user == null) {
throw new UsernameNotFoundException("User " + name + " not found!");
}
Collection<GrantedAuthority> auth = getAuthorities(user.getAuthorities());
return new User(user.getName(), user.getPassword(), true, true, true, true, auth);
}
Ahora, en un bean de autenticación, todo lo que necesita es inyectar este bean y solicitar el UserDetails. Allí puede usarlo para verificar si las credenciales son correctas y, de ser así, complete el SecurityContext con la información necesaria para iniciar sesión.
@Override
public Boolean authenticate(String username, String password) {
UserDetails userdetail = null;
try {
userdetail = myUserService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
return false;
} catch (DataAccessException e) {
return false;
}
if (!myUserService.encodePassword(password).equals(userdetail.getPassword())) {
return false;
}
Authentication auth = new UsernamePasswordAuthenticationToken(userdetail.getUsername(), userdetail.getPassword(),
userdetail.getAuthorities());
SecurityContext sc = new SecurityContextImpl();
ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
attr.getRequest().getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, userdetail.getUsername());
sc.setAuthentication(auth);
SecurityContextHolder.setContext(sc);
return true;
}
Por supuesto, esa es una versión simplificada de la real. Hay muchas más comprobaciones que debe realizar antes de decir que el usuario está autenticado (SQLInjection, por ejemplo)
Puede ir al formulario de inicio de sesión de Spring aquí: http://www.roseindia.net/spring/spring-mvc-login-example.shtml .
Si está utilizando una base de datos a la que se puede acceder con JDBC, entonces no necesita crear un proveedor de autenticación personalizado. El proveedor de autenticación ya le permite consultar la base de datos directamente. Reducirá el código requerido a 9 líneas de XML en lugar de una multitud de clases.
He respondido esto aquí con ejemplos de código: autenticación de base de datos Spring Security 3 con Hibernate
Al principio, debe definir este archivo WEB-INF/spring/serurity-context.xml
:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<http auto-config="true" />
<beans:bean id="myUserService" class="org.my.UserService" />
<authentication-provider user-service-ref="myUserService" />
</beans:beans>
Ahora debe crear la clase org.my.UserService
e implementar la interfaz org.springframework.security.core.userdetails.UserDetailsService
. Esta interfaz tiene un método:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, org.springframework.dao.DataAccessException
Y en este método puede usar Hibernate para cargar usuario por userName. Si el usuario no existe, simplemente eche UsernameNotFoundException, de lo contrario, devuelva una nueva instancia de UserDetails inicializada (allí puede proporcionar muchas cosas como funciones de usuario, fecha de caducidad de la cuenta, etc.).
Ahora viene web.xml
:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>My Webapp</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*-context.xml
</param-value>
</context-param>
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Si tiene alguna pregunta o algo sale mal, no dude en preguntar :)
PD: Entonces, con UserDetailsService no tiene que verificar si la cuenta de usuario está activa, etc. Simplemente proporciona información de seguridad de primavera sobre el usuario con el nombre de usuario proporcionado y el marco valida al usuario. Si codifica sus contraseñas con MD5, por ejemplo, entonces puede usar password-encoder
como este:
<beans:bean id="myUserService" class="org.my.UserService" />
<authentication-provider user-service-ref="myUserService">
<password-encoder hash="md5"/>
</authentication-provider>
Actualizar
Ahora profundizaremos más en UserService
: mi ejemplo (simplificado) del mundo real.
Clase UserService
:
import org.my_company.my_app.domain.User
public class UserService implements UserDetailsService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
// load user
User user = userDao.getUser(username);
if (user != null) {
// convert roles
List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
for (Privilege p : user.getPrivileges()) {
roles.add(new GrantedAuthorityImpl(p.getName()));
}
// initialize user
SecurityUser securityUser = new SecurityUser(
user.getUsername(),
user.getLdapAuth() ? getLdapPassword(user.getUsername()) : user.getPassword(),
user.getStatus() != User.Status.NOT_COMMITED, user.getStatus() != User.Status.BLOCKED, true, true,
roles.toArray(new GrantedAuthority[0])
);
securityUser.setUser(user);
return securityUser;
} else {
throw new UsernameNotFoundException("No user with username ''" + username + "'' found!");
}
}
}
Ahora SecurityUser
:
import org.my_company.my_app.domain.User
public class SecurityUser extends org.springframework.security.core.userdetails.User {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public SecurityUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
Y finalmente UserDao
:
import org.my_company.my_app.domain.User
public class UserDao extends HibernateDaoSupport {
public User getUser(String username) {
List users = getHibernateTemplate().find("from User where username = ?", username);
return users == null || users.size() <= 0 ? null : (User) users.get(0);
}
}
Como pueden ver, usé HibernateTemplate
aquí.