2013-05-07 81 views
2

根據Spring文檔,如果您需要通過數據庫管理Spring安全性,則應該有一些標準的表格模式。例如。Spring Security + JPA用戶綱要

create table users(
    username varchar(256) not null primary key, 
    password varchar(256) not null, 
    enabled boolean not null 
); 

create table authorities (
    username varchar(256) not null, 
    authority varchar(256) not null, 
    constraint fk_authorities_users foreign key(username) references users(username) 
); 
create unique index ix_auth_username on authorities (username,authority); 

我面臨的問題是以下。 1)無法理解如何使用JPA實現這種表格模式?

我已經嘗試過如下所示。

@Entity 
@Table(name="USERS") 
public class UsersPersistence extends Users implements Serializable{ 

    private static final long serialVersionUID = 1009548075747154488L; 

    public UsersPersistence() { 
     super(); 
    } 

    public UsersPersistence(long id, String userName, String password, boolean enabled) { 
     super(id, userName,password,enabled); 
    } 

    @Id 
    @GeneratedValue 
    @Column(name="id") 
    @Override 
    public long getId() { 
     return super.getId(); 
    } 

    @Column(name="username", nullable=false) 
    @Override 
    public String getUserName() { 
     return super.getUserName(); 
    } 

    @Column(name="password", nullable=false) 
    @Override 
    public String getPassword() { 
     return super.getPassword(); 
    } 

    @Column(name="enabled", nullable=false) 
    @Override 
    public boolean isEnabled() { 
     return super.isEnabled(); 
    } 

} 

根據Spring文檔模式中的要求創建此表。 理解問題是當我試圖在權限表中的用戶名分配一個外鍵。由於JPA通過父表的id(主鍵表)分配外鍵或者可能我不知道如何分配它。

以下是創建問題JPA類: - 創建成功

@Entity 
@Table(name="AUTHORITIES") 
public class AuthoritiesPersistence extends Authorities implements Serializable{ 

    private static final long serialVersionUID = 1L; 

    public AuthoritiesPersistence() { 
     super(); 
    } 

    public AuthoritiesPersistence(long id, UsersPersistence userName, String authority) { 
     super(id,userName,authority); 
    } 

    @Id 
    @GeneratedValue 
    @Column(name="id") 
    @Override 
    public long getId() { 
     return super.getId(); 
    } 

    @Override 
    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="username", nullable=false) 
    public UsersPersistence getUserName() { 
     return (UsersPersistence) super.getUserName(); 
    } 

    @Column(name="authority", nullable=false) 
    @Override 
    public String getAuthority() { 
     return super.getAuthority(); 
    } 

} 

此表,但因爲JPA使用比實際用戶名的外鍵ID Spring Security認證是無法識別的用戶名。

任何幫助將是可觀的。我真的堅持創建一個基於用戶名而不是id的外鍵。 感謝

+0

你不必在你的表中指定的ID。 – 2013-05-07 08:47:55

+0

首先感謝您的快速回復@Kelvin。在這兩個表中都指定了Id。兩個持久化類都擴展了一些父類。這些類有id和持久化類,我只是重寫這些getters並將它們分配在表id列中。 – 2013-05-07 08:50:59

+0

但ddl沒有提到id列 – 2013-05-07 09:02:47

回答

2

你只需要堅持使用默認JdbcDaoImplUserDetailsService實施,這是情況下,如果你在你的安全配置<jdbc-user-service>標記時,Spring Security的參考文檔中給出的架構。即使這樣,也可以覆蓋它用來提取用戶和權限的默認SQL查詢(請參閱namespace appendix)。

但是,如果您使用hibernate管理用戶帳戶,那麼編寫自己的UserDetailsService實現將非常有意義,而不是嘗試創建導致JdbcDaoImpl所需的特定模式的JPA實體。

documentation狀態,以及:

如果應用程序使用了一個ORM工具,你可能更願意編寫自定義的UserDetailsS​​ervice重用你可能已經創建的映射文件。

+0

感謝您的回覆@ zagyi。根據規範,您無法更改架構。問題從來都不是關於什麼規範說的。問題是有沒有什麼辦法可以通過JPA來實現該模式。 – 2013-05-07 09:15:29

+0

我的意思是說,就你而言,忘記使用''可能會更容易,它是默認模式。實現你自己的'UserDetailsS​​ervice'對於hibernate來說幾乎是微不足道的,它在任何情況下都不會被認爲是一種黑客或者非標準的實現身份驗證的方式。 – zagyi 2013-05-07 09:34:16

0

我弄不清替代該「配置JdbcUserDetailsManager使用自定義的SQL查詢」至少我可以通過JPA創建我的表,而且可以希望 「用戶按用戶名查詢和當局逐用戶名 - 查詢「將確實做我的工作。 爲了實現它,我必須添加以下模式。

create table custom_user_authorities (
    id bigint identity, 
    user bigint not null, 
    authority varchar(256) not null, 
); 

此模式有id(將自動遞增),這肯定會用於JPA。

1

有幾個方法,你可以處理這個問題:

要你要知道的是,除了用你感興趣的方法從具有域用戶名,密碼和啓用春季安全預期用戶名是一個唯一的標識符。這意味着你可以使用你的實體的username屬性作爲你的DB和Hibernate的Id。 如果你不想這樣做,接近這個的方法是設置一個表,並使用ID /名稱和權限來定義授權。然後設置使用連接表將它們映射到用戶。 一些未經檢驗的examplecode: 角色:

@Entity 
@DynamicUpdate 
@Table(name ="authorities") 
public class Authority{ 


    private String authority; 

    @Id 
    @Column(name="authority") 
    public String getAuthority() { 
     return authority; 
    } 

用戶:

@Entity 
@DynamicUpdate 
@Table(name = "users", uniqueConstraints={ @UniqueConstraint(columnNames={"username"})}) 
public class User { 
private String username; 
private List<Authority> authorities; 
@Type(type = "numeric_boolean") 
    private boolean enabled; 


     @Id 
    @Column(name="username") 
    public String getUsername() { 
     return username; 
    } 

     @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(
     name = "authorities", 
     joinColumns = @JoinColumn(name = "username"), 
     inverseJoinColumns = @JoinColumn(name = "rolename") 
    ) 
    public List<Authority> getauthorities() { 
     return authorities; 
    } 

     @Column(name="ENABLED") 
    public boolean isEnabled() { 
     return enabled; 
    } 

當底座運行時,你可以在內部使用添加屬性爲u喜歡。

0

我能夠使用下面的類定義的表映射:

@Entity 
@Table(name = "users") 
public class User { 

    @Id 
    @Column(name = "username") 
    private String username; 
    @Column(name = "password") 
    private String password; 
    @Column 
    private boolean enabled; 
    @Column 
    private String firstName; 
    @ElementCollection 
    @JoinTable(name = "authorities", joinColumns = {@JoinColumn(name = "email")}) 
    @Column(name = "authority") 
    private Set<String> roles; 

    public User() { 
    } 

    public Serializable getId() { 
     return username; 
    } 

    public String getUsername() { 
     return username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public boolean isEnabled() { 
     return enabled; 
    } 

    public void setEnabled(boolean enabled) { 
     this.enabled = enabled; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public Set<String> getRoles() { 
     return roles; 
    } 

    public void setRoles(Set<String> roles) { 
     this.roles = roles; 
    } 

}