Why would you want to have a design that can backfire you in the future? You really have to think ahead and apply good design practices on your project. This topic pops up here almost every day.
In Spring context, a role actually is an authority. I have no idea why this is made so complex by design by them. You either can have a 1) very simple approach where you assign a role which in fact is authority to an user or 2) more complex solution which includes user, role and permission. The idea would be to assign permissions to roles and assign roles to user. In this solution role
entity only serves a purpose of grouping the granted permissions together as one bundle, but through your authentication manager you assign permissions through roles.
Note: I am using common base @MappedSuperclass
for my entities.
First, have an User entity:
@Entity
@Table(name = "user_t")
public class User extends BaseEntity {
@Column(name = "username", nullable = false, unique = true)
private String userName;
@Column(name = "password", nullable = false)
private String password;
@ManyToMany
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> role = new HashSet<Role>();
// builder/getters/setters
}
Role entity
@Entity(name = "role_t")
@Column(name = "role_name", nullable = false)
private String roleName;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "permission_id"))
private Set<Permission> permissions;
// getters/setters
}
Permission entity
@Entity(name = "permission_t")
public class Permission extends BaseEntity implements GrantedAuthority {
@Column (name = "permission_name", nullable = false)
private String permissionName;
public String getPermissionName() {
return permissionName;
}
public void setPermissionName(String permissionName) {
this.permissionName = permissionName;
}
@Override
public String getAuthority() {
return permissionName;
}
@Override
public int hashCode() {
return permissionName.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj == null) return false;
if(!(obj instanceof Permission)) return false;
return ((Permission) obj).getAuthority().equals(permissionName);
}
Now in your AuthenticationManager
or whatever you decide to use, you loop throug the roles and assign the permissions that are assigned to the roles to the user, if that makes sense.
CustomAuthenticationProvider
public class AppAuthProvider implements AuthenticationProvider {
private static final String PERMISSION_PREFIX = "ROLE_PERMISSION_";
// get the logging user info
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Collection<GrantedAuthority> permissions = new HashSet<GrantedAuthority>();
for (Role role : user.getRole()) {
for (Permission perm : role.getPermissions()) {
GrantedAuthority permission = new SimpleGrantedAuthority(PERMISSION_PREFIX + perm.getPermissionName());
permissions.add(permission);
}
}
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user, null, permissions); // user object you get from service/repository
return authToken;
}
}