]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Improve Jackrabbit security
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
1 package org.argeo.security.jackrabbit;
2
3 import java.security.Principal;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Set;
8
9 import javax.jcr.RepositoryException;
10 import javax.jcr.Session;
11 import javax.security.auth.Subject;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.apache.jackrabbit.api.security.user.Group;
16 import org.apache.jackrabbit.api.security.user.User;
17 import org.apache.jackrabbit.api.security.user.UserManager;
18 import org.apache.jackrabbit.core.DefaultSecurityManager;
19 import org.apache.jackrabbit.core.RepositoryImpl;
20 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
21 import org.apache.jackrabbit.core.security.SecurityConstants;
22 import org.apache.jackrabbit.core.security.SystemPrincipal;
23 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
24 import org.argeo.ArgeoException;
25 import org.springframework.security.Authentication;
26 import org.springframework.security.GrantedAuthority;
27
28 /** Intermediary class in order to have a consistent naming in config files. */
29 public class ArgeoSecurityManager extends DefaultSecurityManager {
30 private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
31
32 @Override
33 /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
34 public String getUserID(Subject subject, String workspaceName)
35 throws RepositoryException {
36 long begin = System.currentTimeMillis();
37
38 if (!subject.getPrincipals(SystemPrincipal.class).isEmpty())
39 return super.getUserID(subject, workspaceName);
40
41 Authentication authen;
42 Set<Authentication> authens = subject
43 .getPrincipals(Authentication.class);
44 if (authens.size() == 0)
45 throw new ArgeoException("No Spring authentication found in "
46 + subject);
47 else
48 authen = authens.iterator().next();
49
50 UserManager systemUm = getSystemUserManager(workspaceName);
51
52 String userId = authen.getName();
53 User user = (User) systemUm.getAuthorizable(userId);
54 if (user == null) {
55 user = systemUm.createUser(userId, authen.getCredentials()
56 .toString(), authen, null);
57 log.info(userId + " added as " + user);
58 }
59
60 List<String> userGroupIds = new ArrayList<String>();
61 for (GrantedAuthority ga : authen.getAuthorities()) {
62 Group group = (Group) systemUm.getAuthorizable(ga.getAuthority());
63 if (group == null) {
64 group = systemUm.createGroup(ga.getAuthority(),
65 new GrantedAuthorityPrincipal(ga), null);
66 log.info(ga.getAuthority() + " added as " + group);
67 }
68 if (!group.isMember(user))
69 group.addMember(user);
70 userGroupIds.add(ga.getAuthority());
71 }
72
73 // check if user has not been removed from some groups
74 for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
75 Group group = it.next();
76 if (!userGroupIds.contains(group.getID()))
77 group.removeMember(user);
78 }
79
80 if (log.isTraceEnabled())
81 log.trace("Spring and Jackrabbit Security synchronized for user "
82 + userId + " in " + (System.currentTimeMillis() - begin)
83 + " ms");
84 return userId;
85 }
86
87 @Override
88 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
89 WorkspaceAccessManager wam = super
90 .createDefaultWorkspaceAccessManager();
91 return new ArgeoWorkspaceAccessManagerImpl(wam);
92 }
93
94 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
95 WorkspaceAccessManager {
96 private final WorkspaceAccessManager wam;
97 private String defaultWorkspace;
98
99 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
100 super();
101 this.wam = wam;
102 }
103
104 public void init(Session systemSession) throws RepositoryException {
105 wam.init(systemSession);
106 defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
107 .getDefaultWorkspaceName();
108 }
109
110 public void close() throws RepositoryException {
111 }
112
113 public boolean grants(Set<Principal> principals, String workspaceName)
114 throws RepositoryException {
115 // anonymous has access to the default workspace (required for
116 // remoting which does a default login when initializing the
117 // repository)
118 Boolean anonymous = false;
119 for (Principal principal : principals)
120 if (principal instanceof AnonymousPrincipal)
121 anonymous = true;
122
123 if (anonymous && workspaceName.equals(defaultWorkspace))
124 return true;
125 else
126 return wam.grants(principals, workspaceName);
127 }
128 }
129
130 }