I want to use JAAS in my project, configuring a JDBCRealm through JPA entities. The authentication seems to work correctly, for example, I try to access facelet /admin/analysis.xhtml
and redirect me to facet login.xhtml
. When I enter the username and password the user shows me an error page 403 of glassfish indicating that I am not allowed to access. But this user does have assigned the role Administrator in the roles table.
Next I expose all the configuration:
JPA entities:
@Entity(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "USER_NAME")
private String userName;
@Column(name = "PASSWD", length = 32,
columnDefinition = "VARCHAR(32)")
private char[] password;
@OneToOne(fetch = FetchType.EAGER,
cascade = CascadeType.ALL, mappedBy = "user")
private Role role;
private String name;
private String lastname;
@ManyToOne
private Province province;
public User() {
}
public User(String userName, char[] password, ROLE role) {
this.userName = userName;
this.password = hashPassword(password);
this.role = new Role(role, this);
}
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = hashPassword(password);
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
role.setUser(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Province getProvince() {
return province;
}
public void setProvince(Province province) {
this.province = province;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final User other = (User) obj;
if ((this.userName == null) ? (other.userName != null) :
!this.userName.equals(other.userName)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 83 * hash + (this.userName != null ? this.userName.hashCode() : 0);
return hash;
}
@Override
public String toString() {
return "User{" + "userName=" + userName + ", password=" + password + ", role=" + role + '}';
}
private char[] hashPassword(char[] password) {
char[] encoded = null;
try {
ByteBuffer passwdBuffer =
Charset.defaultCharset().encode(CharBuffer.wrap(password));
byte[] passwdBytes = passwdBuffer.array();
MessageDigest mdEnc = MessageDigest.getInstance("MD5");
mdEnc.update(passwdBytes, 0, password.length);
encoded = new BigInteger(1, mdEnc.digest()).toString(16).toCharArray();
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
}
return encoded;
}
}
@Entity(name = "ROLES")
public class Role implements Serializable {
public static enum ROLE {
ADMINISTRATOR, USER
}
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ROLE_NAME")
@Enumerated(EnumType.STRING)
private ROLE role;
@Id
@OneToOne
@JoinColumn(name = "USER_NAME")
private User user;
protected Role() {
}
protected Role(ROLE role, User user) {
this.role = role;
this.user = user;
}
public ROLE getRole() {
return role;
}
public void setRole(ROLE role) {
this.role = role;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Role other = (Role) obj;
if (this.role != other.role) {
return false;
}
if (this.user != other.user && (this.user == null ||
!this.user.equals(other.user))) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + (this.role != null ? this.role.hashCode() : 0);
hash = 89 * hash + (this.user != null ? this.user.hashCode() : 0);
return hash;
}
@Override
public String toString() {
return "Role{" + "role=" + role + ", user=" + user + '}';
}
}
The JDBCRealm:
And finally the deployment descriptor configuration of the web layer:
<security-constraint>
<display-name>Security Constraints</display-name>
<web-resource-collection>
<web-resource-name>Only Admin</web-resource-name>
<description>only admin resources</description>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>ADMINISTRATOR</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/login-error.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description>Administradores</description>
<role-name>ADMINISTRATOR</role-name>
</security-role>
<security-role>
<description>Usuario normal</description>
<role-name>USER</role-name>
</security-role>
The database has the following records:
INSERT INTO SERGIO11.USERS (USER_NAME, LASTNAME, "NAME", PASSWD, PROVINCE_ID)
VALUES ('sergio11', 'Sánchez', 'Sergio', 'eaa66f1a644c8a09ca3c584f415c0c49', NULL);
INSERT INTO SERGIO11.ROLES (ROLE_NAME, USER_NAME)
VALUES ('ADMINISTRATOR', 'sergio11');
Thank you very much in advance;) !!