1 package net.ramapuram.thomas.service;
2
3 import org.apache.commons.collections.CollectionUtils;
4 import org.apache.commons.logging.Log;
5 import org.apache.commons.logging.LogFactory;
6 import net.ramapuram.thomas.Constants;
7 import net.ramapuram.thomas.model.Role;
8 import net.ramapuram.thomas.model.User;
9 import org.springframework.aop.AfterReturningAdvice;
10 import org.springframework.aop.MethodBeforeAdvice;
11 import org.springframework.security.access.AccessDeniedException;
12 import org.springframework.security.authentication.AuthenticationTrustResolver;
13 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
14 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
15 import org.springframework.security.core.Authentication;
16 import org.springframework.security.core.GrantedAuthority;
17 import org.springframework.security.core.context.SecurityContext;
18 import org.springframework.security.core.context.SecurityContextHolder;
19 import org.springframework.security.core.userdetails.UserDetails;
20
21 import java.lang.reflect.Method;
22 import java.util.Collection;
23 import java.util.HashSet;
24 import java.util.Set;
25
26
27
28
29
30
31
32 public class UserSecurityAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
33
34
35
36 public static final String ACCESS_DENIED = "Access Denied: Only administrators are allowed to modify other users.";
37 private final Log log = LogFactory.getLog(UserSecurityAdvice.class);
38
39
40
41
42
43
44
45
46
47
48 public void before(Method method, Object[] args, Object target) throws Throwable {
49 SecurityContext ctx = SecurityContextHolder.getContext();
50
51 if (ctx.getAuthentication() != null) {
52 Authentication auth = ctx.getAuthentication();
53 boolean administrator = false;
54 Collection<GrantedAuthority> roles = auth.getAuthorities();
55 for (GrantedAuthority role1 : roles) {
56 if (role1.getAuthority().equals(Constants.ADMIN_ROLE)) {
57 administrator = true;
58 break;
59 }
60 }
61
62 User user = (User) args[0];
63
64 AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
65
66 boolean signupUser = resolver.isAnonymous(auth);
67
68 if (!signupUser) {
69 User currentUser = getCurrentUser(auth);
70
71 if (user.getId() != null && !user.getId().equals(currentUser.getId()) && !administrator) {
72 log.warn("Access Denied: '" + currentUser.getUsername() + "' tried to modify '" + user.getUsername() + "'!");
73 throw new AccessDeniedException(ACCESS_DENIED);
74 } else if (user.getId() != null && user.getId().equals(currentUser.getId()) && !administrator) {
75
76 Set<String> userRoles = new HashSet<String>();
77 if (user.getRoles() != null) {
78 for (Object o : user.getRoles()) {
79 Role role = (Role) o;
80 userRoles.add(role.getName());
81 }
82 }
83
84
85 Set<String> authorizedRoles = new HashSet<String>();
86 for (GrantedAuthority role : roles) {
87 authorizedRoles.add(role.getAuthority());
88 }
89
90
91
92 if (!CollectionUtils.isEqualCollection(userRoles, authorizedRoles)) {
93 log.warn("Access Denied: '" + currentUser.getUsername() + "' tried to change their role(s)!");
94 throw new AccessDeniedException(ACCESS_DENIED);
95 }
96 }
97 } else {
98 if (log.isDebugEnabled()) {
99 log.debug("Registering new user '" + user.getUsername() + "'");
100 }
101 }
102 }
103 }
104
105
106
107
108
109
110
111
112
113 public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
114 throws Throwable {
115 User user = (User) args[0];
116
117 if (user.getVersion() != null) {
118
119 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
120 AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
121
122 boolean signupUser = resolver.isAnonymous(auth);
123 if (auth != null && !signupUser) {
124 User currentUser = getCurrentUser(auth);
125 if (currentUser.getId().equals(user.getId())) {
126 auth = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
127 SecurityContextHolder.getContext().setAuthentication(auth);
128 }
129 }
130 }
131 }
132
133 private User getCurrentUser(Authentication auth) {
134 User currentUser;
135 if (auth.getPrincipal() instanceof UserDetails) {
136 currentUser = (User) auth.getPrincipal();
137 } else if (auth.getDetails() instanceof UserDetails) {
138 currentUser = (User) auth.getDetails();
139 } else {
140 throw new AccessDeniedException("User not properly authenticated.");
141 }
142 return currentUser;
143 }
144 }