getActiveSessions() {
104 | return map.values();
105 | }
106 |
107 | /**
108 | * Retrieves a collection of sessions related to a user.
109 | *
110 | * @param email the authentication identifier to look sessions for.
111 | * @return a collection of sessions.
112 | */
113 | public Collection getSessionsForAuthenticationEntity(
114 | final String email) {
115 | log.debug("Looking up for sessions related to [{}]", email);
116 | final SessionAttributePredicate predicate
117 | = new SessionAttributePredicate<>("email", email);
118 | return map.values(predicate);
119 | }
120 |
121 | /**
122 | * Destroys currently allocated instance.
123 | */
124 | public void destroy() {
125 | log.info("Shutting down Hazelcast instance [{}]..", hcInstanceName);
126 | final HazelcastInstance instance = Hazelcast.getHazelcastInstanceByName(
127 | hcInstanceName);
128 | if (instance != null) {
129 | instance.shutdown();
130 | }
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/src/main/java/com/github/pires/example/shiro/OrientDbRealm.java:
--------------------------------------------------------------------------------
1 | package com.github.pires.example.shiro;
2 |
3 | import com.github.pires.example.model.Permission;
4 | import com.github.pires.example.model.Role;
5 | import com.github.pires.example.model.User;
6 | import com.github.pires.example.repository.UserRepository;
7 |
8 | import java.util.LinkedHashSet;
9 | import java.util.Set;
10 |
11 | import org.apache.shiro.authc.AuthenticationException;
12 | import org.apache.shiro.authc.AuthenticationInfo;
13 | import org.apache.shiro.authc.AuthenticationToken;
14 | import org.apache.shiro.authc.SimpleAuthenticationInfo;
15 | import org.apache.shiro.authc.UnknownAccountException;
16 | import org.apache.shiro.authc.UsernamePasswordToken;
17 | import org.apache.shiro.authz.AuthorizationInfo;
18 | import org.apache.shiro.authz.SimpleAuthorizationInfo;
19 | import org.apache.shiro.realm.AuthorizingRealm;
20 | import org.apache.shiro.subject.PrincipalCollection;
21 | import org.apache.shiro.util.ByteSource;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.stereotype.Component;
24 |
25 | /**
26 | * Shiro authentication & authorization realm that relies on OrientDB as
27 | * datastore.
28 | */
29 | @Component
30 | public class OrientDbRealm extends AuthorizingRealm {
31 |
32 | @Autowired
33 | private UserRepository userRepository;
34 |
35 | @Override
36 | protected AuthenticationInfo doGetAuthenticationInfo(
37 | final AuthenticationToken token)
38 | throws AuthenticationException {
39 | final UsernamePasswordToken credentials = (UsernamePasswordToken) token;
40 | final String email = credentials.getUsername();
41 | if (email == null) {
42 | throw new UnknownAccountException("Email not provided");
43 | }
44 | final User user = userRepository.findByEmailAndActive(email, true);
45 | if (user == null) {
46 | throw new UnknownAccountException("Account does not exist");
47 | }
48 | return new SimpleAuthenticationInfo(email, user.getPassword().toCharArray(),
49 | ByteSource.Util.bytes(email), getName());
50 | }
51 |
52 | @Override
53 | protected AuthorizationInfo doGetAuthorizationInfo(
54 | final PrincipalCollection principals) {
55 | // retrieve role names and permission names
56 | final String email = (String) principals.getPrimaryPrincipal();
57 | final User user = userRepository.findByEmailAndActive(email, true);
58 | if (user == null) {
59 | throw new UnknownAccountException("Account does not exist");
60 | }
61 | final int totalRoles = user.getRoles().size();
62 | final Set roleNames = new LinkedHashSet<>(totalRoles);
63 | final Set permissionNames = new LinkedHashSet<>();
64 | if (totalRoles > 0) {
65 | for (Role role : user.getRoles()) {
66 | roleNames.add(role.getName());
67 | for (Permission permission : role.getPermissions()) {
68 | permissionNames.add(permission.getName());
69 | }
70 | }
71 | }
72 | final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
73 | info.setStringPermissions(permissionNames);
74 | return info;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/github/pires/example/shiro/SessionAttributePredicate.java:
--------------------------------------------------------------------------------
1 | package com.github.pires.example.shiro;
2 |
3 | import com.hazelcast.query.Predicate;
4 |
5 | import java.io.Serializable;
6 | import java.util.Map;
7 |
8 | import org.apache.shiro.session.Session;
9 |
10 | /**
11 | * Hazelcast query predicate for Shiro session attributes.
12 | */
13 | public class SessionAttributePredicate implements
14 | Predicate {
15 |
16 | private final String attributeName;
17 | private final T attributeValue;
18 |
19 | public SessionAttributePredicate(String attributeName, T attributeValue) {
20 | this.attributeName = attributeName;
21 | this.attributeValue = attributeValue;
22 | }
23 |
24 | public String getAttributeName() {
25 | return attributeName;
26 | }
27 |
28 | public T getAttributeValue() {
29 | return attributeValue;
30 | }
31 |
32 | @Override
33 | public boolean apply(Map.Entry sessionEntry) {
34 | final T attribute = (T) sessionEntry.getValue().getAttribute(attributeName);
35 | return attribute.equals(attributeValue);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring.data.orient:
2 | url: memory:orientdb/test1test
3 | username: admin
4 | password: admin
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/test/java/com/github/pires/example/rest/UserControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.pires.example.rest;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.github.pires.example.Application;
6 | import com.github.pires.example.OrientDbConfiguration;
7 | import com.github.pires.example.ShiroConfiguration;
8 | import com.github.pires.example.model.Permission;
9 | import com.github.pires.example.model.Role;
10 | import com.github.pires.example.model.User;
11 | import com.github.pires.example.repository.PermissionRepository;
12 | import com.github.pires.example.repository.RoleRepository;
13 | import com.github.pires.example.repository.UserRepository;
14 |
15 | import java.util.Arrays;
16 |
17 | import org.apache.shiro.authc.UsernamePasswordToken;
18 | import org.apache.shiro.authc.credential.DefaultPasswordService;
19 |
20 | import static org.hamcrest.CoreMatchers.equalTo;
21 | import static org.hamcrest.MatcherAssert.assertThat;
22 |
23 | import org.springframework.beans.factory.annotation.Autowired;
24 | import org.springframework.boot.test.IntegrationTest;
25 | import org.springframework.boot.test.SpringApplicationConfiguration;
26 | import org.springframework.boot.test.TestRestTemplate;
27 | import org.springframework.boot.test.TestRestTemplate.HttpClientOption;
28 | import org.springframework.http.HttpEntity;
29 | import org.springframework.http.HttpHeaders;
30 | import org.springframework.http.HttpMethod;
31 | import org.springframework.http.HttpStatus;
32 | import org.springframework.http.MediaType;
33 | import org.springframework.http.ResponseEntity;
34 | import org.springframework.test.context.TestExecutionListeners;
35 | import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
36 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
37 | import org.springframework.test.context.web.WebAppConfiguration;
38 |
39 | import static org.testng.AssertJUnit.assertEquals;
40 |
41 | import org.testng.annotations.BeforeClass;
42 | import org.testng.annotations.Test;
43 |
44 | @SpringApplicationConfiguration(classes
45 | = {Application.class, OrientDbConfiguration.class, ShiroConfiguration.class})
46 | @WebAppConfiguration
47 | @IntegrationTest
48 | @TestExecutionListeners(inheritListeners = false, listeners
49 | = {DependencyInjectionTestExecutionListener.class})
50 | public class UserControllerTest extends AbstractTestNGSpringContextTests {
51 |
52 | private final String BASE_URL = "http://localhost:8080/users";
53 | private final String USER_NAME = "Paulo Pires";
54 | private final String USER_EMAIL = "pjpires@gmail.com";
55 | private final String USER_PWD = "123qwe";
56 | @Autowired
57 | private DefaultPasswordService passwordService;
58 | @Autowired
59 | private UserRepository userRepo;
60 | @Autowired
61 | private RoleRepository roleRepo;
62 | @Autowired
63 | private PermissionRepository permissionRepo;
64 |
65 | @BeforeClass
66 | public void setUp() {
67 | // clean-up users, roles and permissions
68 | userRepo.deleteAll();
69 | roleRepo.deleteAll();
70 | permissionRepo.deleteAll();
71 | // define permissions
72 | final Permission p1 = new Permission();
73 | p1.setName("VIEW_USER_ROLES");
74 | permissionRepo.save(p1);
75 | // define roles
76 | final Role roleAdmin = new Role();
77 | roleAdmin.setName("ADMIN");
78 | roleAdmin.getPermissions().add(p1);
79 | roleRepo.save(roleAdmin);
80 | // define user
81 | final User user = new User();
82 | user.setActive(true);
83 | user.setCreated(System.currentTimeMillis());
84 | user.setEmail(USER_EMAIL);
85 | user.setName(USER_NAME);
86 | user.setPassword(passwordService.encryptPassword(USER_PWD));
87 | user.getRoles().add(roleAdmin);
88 | userRepo.save(user);
89 | }
90 |
91 | @Test
92 | public void test_count() {
93 | assertEquals(1, userRepo.count());
94 | }
95 |
96 | @Test
97 | public void test_authenticate_success() throws JsonProcessingException {
98 | // authenticate
99 | HttpHeaders headers = new HttpHeaders();
100 | headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
101 | headers.setContentType(MediaType.APPLICATION_JSON);
102 | final String json = new ObjectMapper().writeValueAsString(
103 | new UsernamePasswordToken(USER_EMAIL, USER_PWD));
104 | System.out.println(json);
105 | final ResponseEntity response = new TestRestTemplate(
106 | HttpClientOption.ENABLE_COOKIES).exchange(BASE_URL.concat("/auth"),
107 | HttpMethod.POST, new HttpEntity<>(json, headers), String.class);
108 | assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
109 | }
110 |
111 | @Test
112 | public void test_authenticate_failure() throws JsonProcessingException {
113 | // authenticate
114 | HttpHeaders headers = new HttpHeaders();
115 | headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
116 | headers.setContentType(MediaType.APPLICATION_JSON);
117 | final String json = new ObjectMapper().writeValueAsString(
118 | new UsernamePasswordToken(USER_EMAIL, "wrong password"));
119 | System.out.println(json);
120 | final ResponseEntity response = new TestRestTemplate(
121 | HttpClientOption.ENABLE_COOKIES).exchange(BASE_URL.concat("/auth"),
122 | HttpMethod.POST, new HttpEntity<>(json, headers), String.class);
123 | assertThat(response.getStatusCode(), equalTo(HttpStatus.UNAUTHORIZED));
124 | }
125 |
126 | }
127 |
--------------------------------------------------------------------------------