2010-04-21 15 views

Respuesta

132

Tienes que crear tu propio proveedor de autenticación personalizado.

código Ejemplo:

servicio para cargar los usuarios de Hibernate:

import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.core.userdetails.UsernameNotFoundException;  

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService { 

    @Autowired private UserDao dao; 
    @Autowired private Assembler assembler; 

    @Transactional(readOnly = true) 
    public UserDetails loadUserByUsername(String username) 
     throws UsernameNotFoundException, DataAccessException { 

    UserDetails userDetails = null; 
    UserEntity userEntity = dao.findByName(username); 
    if (userEntity == null) 
     throw new UsernameNotFoundException("user not found"); 

    return assembler.buildUserFromUserEntity(userEntity); 
    } 
} 

servicio para convertir su entidad a un objeto de usuario de primavera:

import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.GrantedAuthorityImpl; 
import org.springframework.security.core.userdetails.User; 

@Service("assembler") 
public class Assembler { 

    @Transactional(readOnly = true) 
    User buildUserFromUserEntity(UserEntity userEntity) { 

    String username = userEntity.getName(); 
    String password = userEntity.getPassword(); 
    boolean enabled = userEntity.isActive(); 
    boolean accountNonExpired = userEntity.isActive(); 
    boolean credentialsNonExpired = userEntity.isActive(); 
    boolean accountNonLocked = userEntity.isActive(); 

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    for (SecurityRoleEntity role : userEntity.getRoles()) { 
     authorities.add(new GrantedAuthorityImpl(role.getRoleName())); 
    } 

    User user = new User(username, password, enabled, 
     accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id); 
    return user; 
    } 
} 

Entonces basado en amespace de contexto de aplicación security.xml sería algo como:

<http> 
    <intercept-url pattern="/login.do*" filters="none"/> 
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 
    <form-login login-page="/login.do" 
       authentication-failure-url="/login.do?error=failed" 
       login-processing-url="/login-please.do" /> 
    <logout logout-url="/logoff-please.do" 
      logout-success-url="/logoff.html" /> 
</http> 

<beans:bean id="daoAuthenticationProvider" 
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
    <beans:property name="userDetailsService" ref="userDetailsService"/> 
</beans:bean> 

<beans:bean id="authenticationManager" 
    class="org.springframework.security.authentication.ProviderManager"> 
    <beans:property name="providers"> 
    <beans:list> 
     <beans:ref local="daoAuthenticationProvider" /> 
    </beans:list> 
    </beans:property> 
</beans:bean> 

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
    <password-encoder hash="md5"/> 
    </authentication-provider> 
</authentication-manager> 
+3

Gracias por la respuesta buena y detallada con full código. ¿Puedes decirme por qué se necesita la clase de ensamblador? ¿Por qué no puedes poner ese código en el método loadUserByUsername? – newbie

+1

Tiene razón, no hay una necesidad real para el Ensamblador. Simplemente pensé que era una buena idea mantener el servicio de usuario simple y hacer la conversión reutilizable a través del servicio de ensamblador. – Kdeveloper

+1

también puede verificar el uso del método de usuario no en desuso http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User. html – Necronet

1

Una configuración de Java podría ser algo como esto

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsServiceImpl userDetailsService; 

    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) 
      throws Exception { 

     DaoAuthenticationProvider daoAuthenticationProvider = 
       new DaoAuthenticationProvider(); 
     daoAuthenticationProvider 
       .setUserDetailsService(userDetailsService); 

     auth.authenticationProvider(daoAuthenticationProvider); 
    } 
} 
4

Si está utilizando una base de datos accesible JDBC, entonces podría usar el siguiente proveedor de autenticación y evitar crear uno personalizado. Se reduce el código necesario para 9 líneas de XML:

<authentication-provider> 
    <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password from users where username=?" authorities-by-username-query="select u.username, r.authority from users u, roles r where u.userid = r.userid and u.username =?" /> 
</authentication-provider> 

A continuación, puede configurar su dataSource de la siguiente manera

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/DB_NAME" /> 
    <property name="username" value="root" /> 
    <property name="password" value="password" /> 
</bean> 

Tener un vistazo a este post: http://codehustler.org/blog/spring-security-tutorial-form-login/ que cubre todo lo que necesita saber sobre la personalización de Spring Security form-login.

+0

¿Podemos usar esto con contraseñas hash? – Rafael

+1

Debe poder contraseñas utilizando en la etiqueta . El codificador se refiere al bean de codificación que desea usar, p. org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. Alternativamente, si estás buscando usar algo como SHA, entonces puedes agregar

Cuestiones relacionadas