Estoy tratando de implementar DAO para trabajar con la autenticación de base de datos Spring Security en Hibernate/JPA2. Primavera utiliza siguientes relaciones y asociaciones con el fin de representar usuario & papeles:¿Cómo implementar Spring Security User/Authorities con Hibernate/JPA2?
repesented como PostgreSQL Crear una consulta:
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
);
Usando las implementaciones de a bordo de GrantedAuthorities
, UserDetailsService
y UserDetailsmanager
, todo está bien. Sin embargo, no estoy satisfecho con la implementación de JDBC de Spring y me gustaría escribir las mías. Con el fin de hacerlo, he tratado de crear una representación de las relaciones siguiendo los objetos de negocio:
La entidad de usuario:
@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
y la entidad autoridad como una implementación de 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
Mi problema es el @ManyToOne
assoc. de AppAuthorities
: se supone que es "nombre de usuario", pero intentarlo arroja un error, porque tengo que tipificar ese atributo como String
... mientras que Hibernate espera la entidad asociada. Entonces, lo que intenté es proporcionar la entidad correcta y crear la asociación por @JoinColumn(name = "appuser_fk")
. Esto es, por supuesto, basura, porque para cargar el usuario, tendré la clave foránea en username
, mientras que Hibernate la busca en appuser_fk
, que siempre estará vacía.
Así que aquí está mi pregunta: ¿alguna sugerencia sobre cómo modificar el código mencionado anteriormente con el fin de obtener una implementación correcta de JPA2 del modelo de datos?
Gracias
¡Ah! ¡Esas son buenas noticias! Procederé exactamente como sugieres, gracias. –
¿puedes compartir la URL del proyecto? Ya perdí mis 5 días para hacer un módulo usando la aplicación de seguridad de reposo de primavera api con oauth2. el problema es cuando llamo url está dando datos falsos como "autoridades": null, "accountNonExpired": falso, "accountNonLocked": falso, "credentialsNonExpired": falso, "enabled": falso. – Harsh