Howto mettre en œuvre le Printemps de la Sécurité de l'Utilisateur/Autorités avec Hibernate/JPA2?
Je suis en train de mettre en œuvre des DAOs de travailler avec Ressort de Sécurité de l'authentification de base de données dans Hibernate/JPA2. Printemps utilise les relations suivantes et les associations afin de représenter l'utilisateur & rôles:
présent que postgresql créer une requête:
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
);
L'aide du conseil des implémentations de GrantedAuthorities
, UserDetailsService
et UserDetailsmanager
, tout va bien. Cependant, je ne suis pas satisfait avec le JDBC mise en œuvre de Printemps et voudrais écrire ma propre. Pour ce faire, j'ai essayé de créer une représentation des relations de business objects suivants:
L'entité utilisateur:
@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
Et l'autorité de l'entité au titre de la mise en œuvre 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
Mon problème est le @ManyToOne
assoc. de AppAuthorities
: Il est censé être le "nom d'utilisateur", mais d'essayer et cela déclenche une erreur, parce que j'en ai à classifier que l'attribut comme String
... alors que Hibernate s'attend l'entité associée. Donc, ce que je tryied est réellement fournir la bonne entité et la création de l'association par @JoinColumn(name = "appuser_fk")
. C'est, bien sûr, des ordures, parce que pour le chargement de l'Utilisateur, je vais avoir la clé étrangère dans username
, tandis que Hibernate recherches dans appuser_fk
, qui sera toujours vide.
Voici donc ma question: avez-vous des suggestions sur la façon de modifier le dessus décrite ci-dessus code afin d'obtenir une bonne JPA2 mise en œuvre du modèle de données?
Grâce
OriginalL'auteur Ta Sas | 2010-09-12
Vous devez vous connecter pour publier un commentaire.
Vous
AppAuthority
n'a pas besoin deusername
à tous. Printemps de Sécurité ne peuvent pas s'appuyer sur elle parce qu'elle dépend de laGrantedAuthority
de l'interface qui n'ont pas toutes les méthodes d'accès nom d'utilisateur.Mais la meilleure pratique consiste à découpler votre modèle de domaine à partir du Printemps de Sécurité. Lorsque vous avez un personnalisé
UserDetailsService
, vous n'avez pas besoin d'imiter ni de Ressort de Sécurité par défaut de schéma de base de données, ni son modèle d'objet. VotreUserDetailsService
pouvez charger vos propresAppUser
etAppAuthority
et puis créerUserDetails
etGrantedAuthority
s, basée sur eux. Cela conduit à une conception avec une meilleure séparation des préoccupations.pouvez-vous partager le projet de l'url? j'ai déjà perdu mes 5 jours pour faire un module à l'aide de printemps de démarrage de sécurité de l'api rest avec oauth2. le problème est que lorsque j'appelle l'url est de donner de fausses données comme des "autorités": null, "accountNonExpired": false, "accountNonLocked": false, "credentialsNonExpired": false, "activé": faux.
OriginalL'auteur axtavt
Cela ressemble à du classique Hibernate problème de l'utilisation d'un domaine-clé spécifique. Une solution possible serait de créer un nouveau champ de clé primaire; par exemple,
userId int
pour laUsers
etAuthorities
entités /tables, enleverAuthorities.userName
, et le changementUsers.userName
à une unique clé secondaire.OriginalL'auteur Stephen C
Il n'y a plus d'une façon qui découple les UserDetailsService de JPA/Hibernate.
Vous pouvez le modèle de votre Utilisateur et de l'Autorité de la classe que vous le souhaitez et utiliser ce alors que la définition de userDetailsService dans la configuration:-
De cette façon, vous pouvez définir amende à l'écoute de la requête SQL pour récupérer de l'utilisateur et de rôles à partir de votre base de données.
Tout ce que vous devez est de prendre soin de la table et de colonne nom.
OriginalL'auteur Kumar Sambhav