2010-04-21 173 views
68

我需要從數據庫驗證用戶,Spring Security文檔不會告訴如何使用hibernate進行身份驗證。這是可能的,我該怎麼做?Spring Security 3使用Hibernate進行數據庫身份驗證

+0

請參閱http://stackoverflow.com/questions/2318467/how-do-i-configure-spring-security-2-database-authentication-with-hibernate-3-ann – axtavt 2010-04-21 13:33:50

回答

132

您必須創建自己的自定義身份驗證提供程序。

示例代碼:

服務從休眠加載用戶:

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

服務到您的實體轉換爲彈簧用戶對象:

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

然後基於amespace的應用程序上下文-security.xml文件看起來是這樣的:

<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

感謝您提供完整且詳細的答案碼。你能告訴我爲什麼需要Assembler類,爲什麼你不能把這些代碼放在loadUserByUsername方法中? – newbie 2010-04-24 10:06:48

+1

你說得對,彙編程序沒有真正的需要。只是認爲保持userDetailsS​​ervice簡單並通過彙編器服務使轉換可重用是一個好主意。 – Kdeveloper 2010-04-24 20:12:11

+1

你也希望檢查使用用戶的非棄用方法http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User。 html – Necronet 2011-03-03 16:52:10

1

一個java的配置可以。如果你使用JDBC訪問數據庫是這個樣子

@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

,那麼你可以使用以下身份驗證提供程序並避免創建自定義提供程序。它減少了需要9線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> 

然後,您可以設置您的數據源如下

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

看一看這個帖子:http://codehustler.org/blog/spring-security-tutorial-form-login/ 它涵蓋了你需要知道的一切關於定製Spring Security表單登錄。

+0

我們可以使用散列密碼嗎? – Rafael 2015-02-25 14:53:31

+1

您應該能夠在標記中使用對密碼進行哈希處理。編碼器是指你想使用的編碼bean,例如org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder。另外,如果你想使用SHA等東西,那麼你可以添加 2015-02-26 20:50:31

相關問題