2012-07-06 146 views
1

我一直在使用Spring Security在SpringMVC中創建有用的表單登錄。我在這方面很新手,也是Hibernate。我想創建簡單的表單登錄,可以訪問我的Web應用程序。SpringSecurity使用UserDetailsS​​ervice和Hibernate登錄

我已經使用SpringSource Tool Suite創建了我的項目並選擇了Spring Template Project。它使用Maven,我也通過Hibernate類生成註釋和hibernate.cfg.xml。在我的數據庫(HSQLDB)中,我有三個表:用戶,角色和users_roles。第三個包含user_id和role_id,因此它存儲有關用戶角色的信息。我已經通過Hibernate生成了類。

我已經開始編寫實現UserDetailsS​​ervice的類。但我不知道如何正確地做到這一點。在spring-security.xml我已經定義的bean是這樣的:

<bean id="userDetailsService" class="hutter.pl.services.HutterUserDetailsService" /> 

我想用的SHA-256散列saltSource。

<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource"> 
    <property name="userPropertyToUse" value="username"/> 
</bean> 

<security:authentication-manager> 
    <security:authentication-provider user-service-ref="userDetailsService"> 
     <security:password-encoder hash="sha-256"> 
      <security:salt-source ref="saltSource" /> 
     </security:password-encoder> 
    </security:authentication-provider> 
</security:authentication-manager> 

我是否應該使用此解決方案:https://stackoverflow.com/a/1654488/845220? Hibernate擁有類似的類:RolesHome,Roles,Users,UsersHome,UsersRoles,UsersRolesHome。但我真的不知道如何使用這些冬眠班授權用戶。

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

    @Transactional(readOnly = true) 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     UsersHome usersHome = new UsersHome(); 
     //Users user = ...  
     //...    
     return null;  
    } 
} 

你能給我一些提示嗎?

編輯: 我已嘗試添加方法public Users findByLogin(String login)UsersHome類。

public Users findByLogin(String login) { 
    log.debug("getting Users instance with login: " + login); 
    try { 
     Users instance = entityManager.find(Users.class, login); 
     log.debug("get successful"); 
     return instance; 
    } catch (RuntimeException re) { 
     log.error("get failed", re); 
     throw re; 
    } 
} 

而我的UserDetailsS​​ervice的身體看起來像:

UsersHome usersHome = new UsersHome(); 
Users user = usersHome.findByLogin(username); 

但我有錯誤時拋出:

ERROR: my.package.dao.UsersHome - get failed 
java.lang.NullPointerException 
at my.package.dao.UsersHome.findByLogin(UsersHome.java:72) 
at my.package.services.HutterUserDetailsService.loadUserByUsername(MyUserDetailsService.java:19) 
+0

我使用休眠核心版本4.1.4.FINAL和spring.framework在3.1.0.RELEASE。我讀過這個版本不支持。這是真的? – woyaru 2012-07-06 12:10:27

+0

我不明白 - 所以你返回null,然後得到一個空指針異常。您可以遍歷調試器中的MyUserDetailsS​​ervice.loadUserByUsername並查找出現錯誤的部分。 ---換句話說 - 哪個對象爲空? – 2012-07-06 13:11:08

+0

我剛剛意識到由Hibernate生成的類包含'private EntityManager entityManager;'但它沒有在任何地方定義。當'entityManager'使用時,我有NullPointer。我認爲Hibernate類是完整的。所以大概我應該不得不以某種我不知道的方式來管理'entityManager'。 – woyaru 2012-07-06 13:18:18

回答

7

我覺得你並不需要實現一個UserService自己。您可以使用jdbc-user-service與數據源:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/mydb" /> 
    <property name="username" value="root" /> 
    <property name="password" value="password" /> 
</bean> 

<authentication-manager> 
    <authentication-provider> 
    <jdbc-user-service data-source-ref="dataSource" 
     users-by-username-query="select username,password, enabled from users where username=?" 
     authorities-by-username-query="select u.username, ur.authority from users u, user_roles ur where u.user_id = ur.user_id and u.username =?" 
    /> 
    </authentication-provider> 
</authentication-manager> 

隨着性能users-by-username-queryusers-by-username-query您可以定義查詢的Spring Security應使用從數據源接收的用戶和權限。

實現,如果

  • 要返回自定義UserDetails對象的用戶對象和當局
  • 的receival(你可以通過SecurityContextHolder後訪問)自己UserService必要過於複雜和/或不能在jdbc-user-service

,方便查詢定義的一種可能實現的UserDetailsS​​ervice的看起來是這樣的:

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

    @PersistenceContext 
    private EntityManager entityManager; 

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

    // this works only if username is the primary key of user 
    // if thats not the case you have to create a query object to receive the user by username 
    User user = entityManager.find(User.class, username); 

    List<GrantedAuthority> roles = .... // get roles for user, depends on your table structure 

    if (user == null) { 
     // user not found 
     throw new UsernameNotFoundException(); 
    } 
    return new MyUserDetails(user, roles); 
    } 

    private static class MyUserDetails implements UserDetails { 
    private User user; 
    private List<Role> roles; 

    public MyUserDetails(Usere user, List<GrantedAuthority> roles) { 
     this.user = user; 
     this.roles = roles; 
    } 

    public Collection<GrantedAuthority> getAuthorities() { 
     return roles; 
    } 

    public String getPassword() { 
     return user.getPassword(); 
    } 

    public String getUsername() { 
     return user.getUsername(); 
    } 

    // return true for the missing boolean methods.. 
    } 
} 

(語法爲未選中)

對於第一測試它可以幫助禁用密碼編碼器和存儲密碼的數據庫加密。這樣可以避免由於配置錯誤PasswordEncoders而導致身份驗證不起作用的問題。一旦你的用戶服務運行,你可以再次添加一個PasswordEncoder並將散列的密碼存儲在數據庫中。

希望它可以幫助:-)

相關問題