Roberto Sánchez
2014-01-21 b83a0ba903b56562751963c106b4c20352c26087
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package net.curisit.securis.security;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Priorities;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;
import net.curisit.securis.db.User;
import net.curisit.securis.utils.CacheTTL;
import net.curisit.securis.utils.TokenHelper;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
// @PreMatching
@Priority(Priorities.AUTHENTICATION)
public class SecurityInterceptor implements javax.ws.rs.container.ContainerRequestFilter {
   private static final Logger log = LoggerFactory.getLogger(SecurityInterceptor.class);
   @Inject
   private TokenHelper tokenHelper;
   @Context
   private HttpServletRequest servletRequest;
   @Inject
   CacheTTL cache;
   @Context
   Dispatcher dispatcher;
   @Inject
   com.google.inject.Provider<EntityManager> emProvider;
   public void filter(ContainerRequestContext containerRequestContext) throws IOException {
       // log.info("scw {}, {}", scw, scw.getClass());
       log.info("MACHED res: {}", containerRequestContext.getUriInfo().getMatchedResources());
       // dispatcher.getDefaultContextObjects().remove(SecurityContextWrapper.class);
       ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) containerRequestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
       Method method = methodInvoker.getMethod();
       if (!method.isAnnotationPresent(Securable.class))
           return;
       String token = servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PÀRAM);
       if (token == null || !tokenHelper.isTokenValid(token)) {
           log.info("Access denied to '{}', Token not valid.", servletRequest.getPathInfo());
           containerRequestContext.abortWith(Response.status(Status.UNAUTHORIZED).build());
       } else {
           Securable sec = method.getAnnotation(Securable.class);
           // If roles == 0 we only need to validate the token
           String username = tokenHelper.extractUserFromToken(token);
           int userRoles = getUserRoles(username);
           // if (sec.roles() != 0) {
           // if ((sec.roles() & userRoles) == 0) {
           // log.info("User {} has no necessary role to access url: {}", username, servletRequest.getPathInfo());
           // containerRequestContext.abortWith(Response.status(Status.UNAUTHORIZED).build());
           // }
           // }
           Set<Integer> orgs = getUserOrganizations(username);
           BasicSecurityContext scw = new BasicSecurityContext(username, userRoles, servletRequest.isSecure());
           scw.setOrganizationsIds(orgs);
           containerRequestContext.setSecurityContext(scw);
           // Next line provide injection in resource methods
           log.info("TEST context {}", ResteasyProviderFactory.getContextData(BasicSecurityContext.class));
           ResteasyProviderFactory.pushContext(BasicSecurityContext.class, scw);
           // log.info("{}", dispatcher.getDefaultContextObjects());
           // dispatcher.getDefaultContextObjects().put(SecurityContextWrapper.class, secContext);
           log.info("Added custom SecurityContext for user {}", username);
       }
   }
   private Set<Integer> getUserOrganizations(String username) {
       @SuppressWarnings("unchecked")
       Set<Integer> userOrgs = cache.get("orgs_" + username, Set.class);
       if (userOrgs == null) {
           // Theorically this shouldn't be never null, but just in case...
           EntityManager em = emProvider.get();
           User user = em.find(User.class, username);
           if (user != null) {
               userOrgs = user.getAllOrgsIds();
               // We store user orgs in cache only for one hour
               cache.set("orgs_" + username, userOrgs, 3600);
           }
       }
       return userOrgs;
   }
   private int getUserRoles(String username) {
       if (username == null)
           return 0;
       Integer userRoles = cache.get("roles_" + username, Integer.class);
       if (userRoles == null) {
           EntityManager em = emProvider.get();
           User user = em.find(User.class, username);
           if (user != null) {
               userRoles = 0;
               List<Integer> roles = user.getRoles();
               for (Integer rol : roles) {
                   userRoles += rol;
               }
               // We store user roles in cache only for one hour
               cache.set("roles_" + username, userRoles, 3600);
               cache.set("orgs_" + username, user.getOrgsIds(), 3600);
           }
       }
       return userRoles == null ? 0 : userRoles.intValue();
   }
   // @Override
   public ServerResponse preProcess(HttpRequest request, ResourceMethodInvoker method) throws Failure, WebApplicationException {
       // TODO Auto-generated method stub
       return null;
   }
}