2010-04-21 15 views
68

Ich muss Benutzer aus der Datenbank authentifizieren, Spring Security-Dokumente sagen nicht, wie mit Hibernate authentifiziert werden. Ist das möglich und wie kann ich das machen?Spring Security 3 Datenbankauthentifizierung mit Hibernate

+0

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

Antwort

132

Sie müssen Ihren eigenen Authentifizierungsanbieter erstellen.

Beispielcode:

Service-Benutzer aus dem Ruhezustand zu laden:

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, um Ihre Einheit mit einem Federbenutzerobjekt zu konvertieren:

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

Dann amespace-basierte anwendungskontext security.xml würde in etwa so aussehen:

<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

Danke für die gute und detaillierte Antwort mit voller Code. Können Sie mir sagen, warum die Assembler-Klasse benötigt wird, warum können Sie diesen Code nicht einfach in die loadUserByUsername-Methode schreiben? – newbie

+1

Sie haben Recht, es gibt keinen wirklichen Bedarf für den Assembler. Ich denke nur, dass es eine gute Idee ist, den userDetailsService einfach zu halten und die Konvertierung über den Assembler-Dienst wiederverwendbar zu machen. – Kdeveloper

+1

Sie möchten auch überprüfen, verwenden Sie die nicht veraltete Methode des Benutzers http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User. html – Necronet

1

Eine Java-Konfiguration so etwas wie diese

@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

aussehen könnte, wenn Sie eine JDBC zugängliche Datenbank verwenden, können Sie dann könnte den folgenden Authentifizierungsanbieter verwenden und es vermeiden, einen benutzerdefinierten zu erstellen. Er schneidet den Code zu 9 Zeilen von XML erforderlich unten:

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

können Sie dann Setup Ihrer Datenquelle wie folgt

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

einen Blick auf diesen Beitrag vorhanden: http://codehustler.org/blog/spring-security-tutorial-form-login/ Es umfasst alles, was Sie wissen müssen über das Anpassen von Spring Security Formular-Login.

+0

Können wir dies mit Hash-Passwörtern verwenden? – Rafael

+1

Sie sollten Kennwörter mit im -Tag hashen können. Der Kodierer bezieht sich auf die Kodierungsbohne, die Sie verwenden möchten, z. org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. Alternativ können Sie, wenn Sie etwas wie SHA verwenden möchten, hinzufügen –

Verwandte Themen