2010-04-21 7 views
68

Je dois authentifier les utilisateurs à partir de la base de données, les documents Spring Security ne disent pas comment s'authentifier avec Hibernate. Est-ce possible et comment puis-je faire cela?Spring Security 3 authentification de base de données avec Hibernate

+0

Voir http://stackoverflow.com/questions/2318467/how-do-i-configure-spring-security-2-database-authentication-with-hibernate-3-ann – axtavt

Répondre

132

Vous devez créer votre propre fournisseur d'authentification personnalisé.

code Exemple:

service à la charge des utilisateurs 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); 
    } 
} 

service pour convertir votre entité à un objet utilisateur de printemps:

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; 
    } 
} 

Alors à base amespace-application contexte security.xml ressemblerait à quelque chose comme:

<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

Merci pour la réponse bonne et détaillée avec pleine code. Pouvez-vous me dire pourquoi la classe Assembler est nécessaire, pourquoi ne pouvez-vous pas simplement mettre ce code dans la méthode loadUserByUsername ?? – newbie

+1

Vous avez raison, il n'y a pas vraiment besoin de l'assembleur. Juste pensé que c'était une bonne idée de garder le userDetailsService simple et rendre la conversion réutilisable via le service assembleur. – Kdeveloper

+1

vous pouvez également vérifier utiliser la méthode non obsolète de l'utilisateur http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User. html – Necronet

1

Une configuration java pourrait ressembler à ceci

@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 vous utilisez une base de données JDBC accessible, vous pourrait utiliser le fournisseur d'authentification suivant et éviter d'en créer un personnalisé. Il réduit le code requis 9 lignes 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> 

Vous pouvez ensuite configurer votre dataSource comme suit

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

Jetez un oeil à ce poste: http://codehustler.org/blog/spring-security-tutorial-form-login/ Il couvre tout ce que vous devez savoir à propos de la personnalisation du formulaire de connexion Spring Security.

+0

Pouvons-nous utiliser ceci avec des mots de passe hachés? – Rafael

+1

Vous devriez être capable de hacher les mots de passe en utilisant dans la balise . L'encodeur fait référence au bean d'encodage que vous souhaitez utiliser, par ex. org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. Alternativement, si vous cherchez à utiliser quelque chose comme SHA, vous pouvez ajouter

Questions connexes