2 * Copyright (C) 2007-2012 Mathieu Baudier
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";
45 public boolean login() throws LoginException
{
46 boolean loginOk
= super.login();
48 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) SecurityContextHolder
49 .getContext().getAuthentication();
55 public boolean commit() throws LoginException
{
56 boolean commitOk
= super.commit();
58 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) SecurityContextHolder
59 .getContext().getAuthentication();
65 * Returns the Spring {@link org.springframework.security.Authentication}
69 protected Principal
getPrincipal(Credentials credentials
) {
70 org
.springframework
.security
.Authentication authen
= SecurityContextHolder
71 .getContext().getAuthentication();
75 protected Set
<Principal
> getPrincipals() {
76 // clear already registered Jackrabbit principals
77 // clearPrincipals(AdminPrincipal.class);
78 // clearPrincipals(AnonymousPrincipal.class);
79 // clearPrincipals(GrantedAuthorityPrincipal.class);
81 return syncPrincipals();
84 protected Set
<Principal
> syncPrincipals() {
85 // use linked HashSet instead of HashSet in order to maintain the order
86 // of principals (as in the Subject).
87 org
.springframework
.security
.Authentication authen
= (org
.springframework
.security
.Authentication
) principal
;
89 Set
<Principal
> principals
= new LinkedHashSet
<Principal
>();
90 principals
.add(authen
);
92 if (authen
instanceof SystemAuthentication
) {
93 principals
.add(new AdminPrincipal(authen
.getName()));
94 principals
.add(new ArgeoSystemPrincipal(authen
.getName()));
95 } else if (authen
instanceof AnonymousAuthenticationToken
) {
96 principals
.add(new AnonymousPrincipal());
98 for (GrantedAuthority ga
: authen
.getAuthorities()) {
99 principals
.add(new GrantedAuthorityPrincipal(ga
));
100 // FIXME: make it more generic
101 if (adminRole
.equals(ga
.getAuthority()))
102 principals
.add(new AdminPrincipal(authen
.getName()));
106 // remove previous credentials
107 Set
<SimpleCredentials
> thisCredentials
= subject
108 .getPublicCredentials(SimpleCredentials
.class);
109 if (thisCredentials
!= null)
110 thisCredentials
.clear();
111 // override credentials since we did not used the one passed to us
112 // credentials = new SimpleCredentials(authen.getName(), authen
113 // .getCredentials().toString().toCharArray());
119 * Super implementation removes all {@link Principal}, the Spring
120 * {@link org.springframework.security.Authentication} as well. Here we
121 * simply clear Jackrabbit related {@link Principal}s.
124 public boolean logout() throws LoginException
{
125 clearPrincipals(AdminPrincipal
.class);
126 clearPrincipals(ArgeoSystemPrincipal
.class);
127 clearPrincipals(AnonymousPrincipal
.class);
128 clearPrincipals(GrantedAuthorityPrincipal
.class);
130 // we resync with Spring Security since the subject may have been reused
132 // TODO: check if this is clean
133 // subject.getPrincipals().addAll(syncPrincipals());
138 private <T
extends Principal
> void clearPrincipals(Class
<T
> clss
) {
139 Set
<T
> principals
= subject
.getPrincipals(clss
);
140 if (principals
!= null)
144 @SuppressWarnings("rawtypes")
146 protected void doInit(CallbackHandler callbackHandler
, Session session
,
147 Map options
) throws LoginException
{
151 protected boolean impersonate(Principal principal
, Credentials credentials
)
152 throws RepositoryException
, LoginException
{
153 throw new UnsupportedOperationException(
154 "Impersonation is not yet supported");
158 protected Authentication
getAuthentication(final Principal principal
,
159 Credentials creds
) throws RepositoryException
{
160 if (principal
instanceof Group
) {
163 return new Authentication() {
164 public boolean canHandle(Credentials credentials
) {
165 return principal
instanceof org
.springframework
.security
.Authentication
;
168 public boolean authenticate(Credentials credentials
)
169 throws RepositoryException
{
170 return ((org
.springframework
.security
.Authentication
) principal
)