This time code only.
1. Entity classes
You will also have to write simple DAOs for entity classes.
1.1 User
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| package pl.dziurdziak.shiro.jpaRealm.user;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import pl.dziurdziak.shiro.jpaRealm.permission.Permission;
import pl.dziurdziak.shiro.jpaRealm.role.Role;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private long id;
@NotNull
private String login;
@NotNull
@Column(length = 64)
private String password;
@NotNull
@Column(length = 80)
private String salt;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Role> roles;
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
private Set<Permission> permissions;
// getters and setters omitted
}
|
1.2 Role
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package pl.dziurdziak.easyReckoning.model.role;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import pl.dziurdziak.shiro.jpaRealm.user.User;
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue
private long id;
@Size(max = 100)
private String roleName;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
// getters and setters ommitted
}
|
1.3 Permission
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package pl.dziurdziak.shiro.jpaRealm.permission;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import pl.dziurdziak.shiro.jpaRealm.User;
@Entity
@Table(name = "permissions")
public class Permission {
@Id
@GeneratedValue
private long id;
@Size(max = 100)
private String permission;
@ManyToOne()
@JoinColumn(name = "USER_ID")
private User user;
// getters and setters omitted
}
|
2. Realm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
| package pl.dziurdziak.shiro.jpaRealm.realm;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import pl.dziurdziak.shiro.jpaRealm.permission.Permission;
import pl.dziurdziak.shiro.jpaRealm.role.Role;
import pl.dziurdziak.shiro.jpaRealm.user.User;
import pl.dziurdziak.shiro.jpaRealm.user.UserDao;
public class JpaAuthorizingRealm extends AuthorizingRealm {
public static final String REALM_NAME = "MY_REALM";
public static final int HASH_ITERATIONS = 200;
@Inject
private UserDao userDao;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principals) {
final String username = (String) principals.getPrimaryPrincipal();
final User user = userDao.findByLogin(username);
final Set<String> roles = new HashSet<>(user.getRoles().size());
for (final Role role : user.getRoles()) {
roles.add(role.getRoleName());
}
final Set<pl.dziurdziak.shiro.jpaRealm.permission.Permission> permissions = new HashSet<>(user.getPermissions().size());
for (final Permission permission : user.getPermissions()) {
permissions.add(new WildcardPermission(permission.getPermission()));
}
final SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roles);
authorizationInfo.setObjectPermissions(permissions);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) throws AuthenticationException {
if (!(token instanceof UsernamePasswordToken)) {
throw new IllegalStateException("Token has to be instance of UsernamePasswordToken class");
}
final UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
if (userPassToken.getUsername() == null) {
throw new AccountException("Null usernames are not allowed by this realm.");
}
final User user = userDao.findByLogin(userPassToken.getUsername());
final SimpleAccount simpleAccount = new SimpleAccount(user.getLogin(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()),
REALM_NAME);
return simpleAccount;
}
@Override
@Inject
public void setCredentialsMatcher(final CredentialsMatcher credentialsMatcher) {
super.setCredentialsMatcher(credentialsMatcher);
}
}
|
3. Utils class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| package pl.dziurdziak.shiro.jpaRealm;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Produces;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import pl.dziurdziak.shiro.jpaRealm.realm.JpaAuthorizingRealm;
public final class JpaSecurityUtil {
public static final int SALT_LENGTH = 80;
public static final int PASSWORD_LENGTH = 64;
public static String getSalt() {
return new SecureRandomNumberGenerator().nextBytes(60).toBase64();
}
public static String hashPassword(final String value, final String salt) {
final Sha256Hash sha256Hash = new Sha256Hash(value, salt, VaadinAuthorizingRealm.HASH_ITERATIONS);
return sha256Hash.toHex();
}
@Produces
@Default
public CredentialsMatcher getCredentialMatcher() {
final HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);
credentialsMatcher.setHashIterations(JpaAuthorizingRealm.HASH_ITERATIONS);
return credentialsMatcher;
}
@Produces
@Default
public SimpleHash getHash() {
final Sha256Hash sha256Hash = new Sha256Hash();
sha256Hash.setIterations(JpaAuthorizingRealm.HASH_ITERATIONS);
return sha256Hash;
}
}
|
4. Usage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package pl.dziurdziak.shiro.jpaRealm;
import pl.dziurdziak.shiro.jpaRealm.user.User;
import pl.dziurdziak.shiro.jpaRealm.user.UserDao;
public class TestClass {
@Inject
private UserDao userDao;
public void register(final String login, final String password) {
User user = new User();
user.setLogin(login);
user.setSalt(JpaSecurityUtil.getSalt());
user.setPassword(JpaSecurityUtil.hashPassword(password, user.getSalt()));
userDao.persist(user);
}
}
|