2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.security
.jackrabbit
;
18 import java
.security
.Principal
;
19 import java
.security
.acl
.Group
;
20 import java
.util
.LinkedHashSet
;
24 import javax
.jcr
.Credentials
;
25 import javax
.jcr
.RepositoryException
;
26 import javax
.jcr
.Session
;
27 import javax
.jcr
.SimpleCredentials
;
28 import javax
.security
.auth
.callback
.CallbackHandler
;
29 import javax
.security
.auth
.login
.LoginException
;
31 import org
.apache
.jackrabbit
.core
.security
.AnonymousPrincipal
;
32 import org
.apache
.jackrabbit
.core
.security
.authentication
.AbstractLoginModule
;
33 import org
.apache
.jackrabbit
.core
.security
.authentication
.Authentication
;
34 import org
.apache
.jackrabbit
.core
.security
.principal
.AdminPrincipal
;
35 import org
.argeo
.security
.SystemAuthentication
;
36 import org
.springframework
.security
.GrantedAuthority
;
37 import org
.springframework
.security
.context
.SecurityContextHolder
;
38 import org
.springframework
.security
.providers
.anonymous
.AnonymousAuthenticationToken
;
40 /** Jackrabbit login mechanism based on Spring Security */
41 public class ArgeoLoginModule
extends AbstractLoginModule
{
42 // private String adminRole = "ROLE_ADMIN";
44 @SuppressWarnings("unused")
46 public boolean login() throws LoginException
{
47 boolean loginOk
= super.login();
49 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) SecurityContextHolder
50 .getContext().getAuthentication();
55 @SuppressWarnings("unused")
57 public boolean commit() throws LoginException
{
58 boolean commitOk
= super.commit();
60 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) SecurityContextHolder
61 .getContext().getAuthentication();
67 * Returns the Spring {@link org.springframework.security.Authentication}
71 protected Principal
getPrincipal(Credentials credentials
) {
72 org
.springframework
.security
.Authentication authen
= SecurityContextHolder
73 .getContext().getAuthentication();
77 protected Set
<Principal
> getPrincipals() {
78 // clear already registered Jackrabbit principals
79 // clearPrincipals(AdminPrincipal.class);
80 // clearPrincipals(AnonymousPrincipal.class);
81 // clearPrincipals(GrantedAuthorityPrincipal.class);
83 return syncPrincipals();
86 protected Set
<Principal
> syncPrincipals() {
87 // use linked HashSet instead of HashSet in order to maintain the order
88 // of principals (as in the Subject).
89 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) principal
;
91 Set
<Principal
> principals
= new LinkedHashSet
<Principal
>();
92 principals
.add(authen
);
94 if (authen
instanceof SystemAuthentication
) {
95 principals
.add(new AdminPrincipal(authen
.getName()));
96 principals
.add(new ArgeoSystemPrincipal(authen
.getName()));
97 } else if (authen
instanceof AnonymousAuthenticationToken
) {
98 principals
.add(new AnonymousPrincipal());
100 for (GrantedAuthority ga
: authen
.getAuthorities()) {
101 principals
.add(new GrantedAuthorityPrincipal(ga
));
102 // FIXME: make it more generic
103 // if (adminRole.equals(ga.getAuthority()))
104 // principals.add(new AdminPrincipal(authen.getName()));
108 // remove previous credentials
109 Set
<SimpleCredentials
> thisCredentials
= subject
110 .getPublicCredentials(SimpleCredentials
.class);
111 if (thisCredentials
!= null)
112 thisCredentials
.clear();
113 // override credentials since we did not used the one passed to us
114 // credentials = new SimpleCredentials(authen.getName(), authen
115 // .getCredentials().toString().toCharArray());
121 * Super implementation removes all {@link Principal}, the Spring
122 * {@link org.springframework.security.Authentication} as well. Here we
123 * simply clear Jackrabbit related {@link Principal}s.
126 public boolean logout() throws LoginException
{
127 clearPrincipals(AdminPrincipal
.class);
128 clearPrincipals(ArgeoSystemPrincipal
.class);
129 clearPrincipals(AnonymousPrincipal
.class);
130 clearPrincipals(GrantedAuthorityPrincipal
.class);
132 // we resync with Spring Security since the subject may have been reused
134 // TODO: check if this is clean
135 // subject.getPrincipals().addAll(syncPrincipals());
140 private <T
extends Principal
> void clearPrincipals(Class
<T
> clss
) {
141 Set
<T
> principals
= subject
.getPrincipals(clss
);
142 if (principals
!= null)
146 @SuppressWarnings("rawtypes")
148 protected void doInit(CallbackHandler callbackHandler
, Session session
,
149 Map options
) throws LoginException
{
153 protected boolean impersonate(Principal principal
, Credentials credentials
)
154 throws RepositoryException
, LoginException
{
155 throw new UnsupportedOperationException(
156 "Impersonation is not yet supported");
160 protected Authentication
getAuthentication(final Principal principal
,
161 Credentials creds
) throws RepositoryException
{
162 if (principal
instanceof Group
) {
165 return new Authentication() {
166 public boolean canHandle(Credentials credentials
) {
167 return principal
instanceof org
.springframework
.security
.Authentication
;
170 public boolean authenticate(Credentials credentials
)
171 throws RepositoryException
{
172 return ((org
.springframework
.security
.Authentication
) principal
)