Sto cercando di implementare DAO per lavorare con l'autenticazione del database Spring Security in Hibernate/JPA2. Spring usa seguenti relazioni e le associazioni al fine di rappresentare utente & ruoli:Come implementare utenti/autorità di sicurezza Spring con Hibernate/JPA2?
repesented come PostgreSQL creare query:
CREATE TABLE users
(
username character varying(50) NOT NULL,
"password" character varying(50) NOT NULL,
enabled boolean NOT NULL,
CONSTRAINT users_pkey PRIMARY KEY (username)
);
CREATE TABLE authorities
(
username character varying(50) NOT NULL,
authority character varying(50) NOT NULL,
CONSTRAINT fk_authorities_users FOREIGN KEY (username)
REFERENCES users (username) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
Utilizzando le implementazioni a bordo di GrantedAuthorities
, UserDetailsService
e UserDetailsmanager
, tutto è ok. Tuttavia, non sono soddisfatto dell'implementazione JDBC di Spring e vorrei scrivere i miei. Per fare ciò, ho cercato di creare una rappresentazione dei rapporti da seguenti oggetti di business:
L'entità utente:
@Entity
@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"username"})})
public class AppUser implements UserDetails, CredentialsContainer {
private static final long serialVersionUID = -8275492272371421013L;
@Id
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "password", nullable = false)
@NotNull
private String password;
@OneToMany(
fetch = FetchType.EAGER, cascade = CascadeType.ALL,
mappedBy = "appUser"
)
private Set<AppAuthority> appAuthorities;
@Column(name = "accountNonExpired")
private Boolean accountNonExpired;
@Column(name = "accountNonLocked")
private Boolean accountNonLocked;
@Column(name = "credentialsNonExpired")
private Boolean credentialsNonExpired;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "personalinformation_fk", nullable = true)
@JsonIgnore
private PersonalInformation personalInformation;
@Column(name = "enabled", nullable = false)
@NotNull
private Boolean enabled;
public AppUser(
String username,
String password,
boolean enabled,
boolean accountNonExpired,
boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<? extends AppAuthority> authorities,
PersonalInformation personalInformation
) {
if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.appAuthorities = Collections.unmodifiableSet(sortAuthorities(authorities));
this.personalInformation = personalInformation;
}
public AppUser() {
}
@JsonIgnore
public PersonalInformation getPersonalInformation() {
return personalInformation;
}
@JsonIgnore
public void setPersonalInformation(PersonalInformation personalInformation) {
this.personalInformation = personalInformation;
}
// Getters, setters 'n other stuff
e l'entità autorità come l'implementazione di GrantedAuthorities:
@Entity
@Table(name = "authorities", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class AppAuthority implements GrantedAuthority, Serializable {
//~ Instance fields ================================================================================================
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username", nullable = false)
private String username;
@Column(name = "authority", nullable = false)
private String authority;
// Here comes the buggy attribute. It is supposed to repesent the
// association username<->username, but I just don't know how to
// implement it
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "appuser_fk")
private AppUser appUser;
//~ Constructors ===================================================================================================
public AppAuthority(String username, String authority) {
Assert.hasText(authority,
"A granted authority textual representation is required");
this.username = username;
this.authority = authority;
}
public AppAuthority() {
}
// Getters 'n setters 'n other stuff
Il mio problema è l'associazione @ManyToOne
. di AppAuthorities
: Si suppone che sia "nomeutente", ma provare a farlo genera un errore, perché devo digitare quell'attributo come String
... mentre Hibernate si aspetta l'entità associata. Quindi quello che ho provato è in realtà fornire l'entità corretta e creare l'associazione per @JoinColumn(name = "appuser_fk")
. Questo è, naturalmente, spazzatura, perché per caricare l'utente, avrò la chiave esterna username
, mentre ricerca Hibernate per esso in appuser_fk
, che saranno sempre vuota.
Quindi, ecco la mia domanda: qualche suggerimento su come modificare il codice sopra menzionato al fine di ottenere una corretta implementazione JPA2 del modello di dati?
Grazie
Ah! Questa è una fantastica notizia! Procederò esattamente come suggerisci, grazie. –
puoi condividere l'URL del progetto? Ho già sprecato i miei 5 giorni per creare un modulo utilizzando api di sicurezza di avvio a molla con oauth2. il problema è quando chiamo url sta dando i dati falsi come "autorità": null, "accountNonExpired": false, "accountNonLocked": false, "credentialsNonExpired": false, "abilitati": false. – Harsh