2 changed files with 282 additions and 0 deletions
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
/* Copyright 2004, 2005 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package net.sf.acegisecurity.providers.jaas; |
||||
|
||||
import net.sf.acegisecurity.Authentication; |
||||
import net.sf.acegisecurity.context.ContextHolder; |
||||
import net.sf.acegisecurity.context.security.SecureContext; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import javax.security.auth.Subject; |
||||
import javax.security.auth.callback.CallbackHandler; |
||||
import javax.security.auth.login.LoginException; |
||||
import javax.security.auth.spi.LoginModule; |
||||
|
||||
|
||||
/** |
||||
* An implementation of {@link LoginModule} that uses an Acegi Security {@link |
||||
* SecureContext} to provide authentication. <br> |
||||
* This LoginModule provides opposite functionality to the {@link |
||||
* JaasAuthenticationProvider} API, and should not really be used in |
||||
* conjunction. <br> |
||||
* The {@link JaasAuthenticationProvider} allows Acegi to authenticate against |
||||
* Jaas. <br> |
||||
* The SecureContextLoginModule allows a Jaas based application to authenticate |
||||
* against Acegi. |
||||
* |
||||
* @author Brian Moseley |
||||
* @author Ray Krueger |
||||
*/ |
||||
public class SecureContextLoginModule implements LoginModule { |
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final Log log = LogFactory.getLog(SecureContextLoginModule.class); |
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Authentication authen; |
||||
private Subject subject; |
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/** |
||||
* Abort the authentication process by forgetting the Acegi Security |
||||
* <code>Authentication</code>. |
||||
* |
||||
* @return true if this method succeeded, or false if this |
||||
* <code>LoginModule</code> should be ignored. |
||||
* |
||||
* @exception LoginException if the abort fails |
||||
*/ |
||||
public boolean abort() throws LoginException { |
||||
if (authen == null) { |
||||
return false; |
||||
} |
||||
|
||||
authen = null; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Authenticate the <code>Subject</code> (phase two) by adding the Acegi |
||||
* Security <code>Authentication</code> to the <code>Subject</code>'s |
||||
* principals. |
||||
* |
||||
* @return true if this method succeeded, or false if this |
||||
* <code>LoginModule</code> should be ignored. |
||||
* |
||||
* @exception LoginException if the commit fails |
||||
*/ |
||||
public boolean commit() throws LoginException { |
||||
if (authen == null) { |
||||
return false; |
||||
} |
||||
|
||||
subject.getPrincipals().add(authen); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Initialize this <code>LoginModule</code>. Ignores the callback handler, |
||||
* since the code establishing the <code>LoginContext</code> likely won't |
||||
* provide one that understands Acegi Security. Also ignores the |
||||
* <code>sharedState</code> and <code>options</code> parameters, since |
||||
* none are recognized. |
||||
* |
||||
* @param subject the <code>Subject</code> to be authenticated. <p> |
||||
* @param callbackHandler is ignored |
||||
* @param sharedState is ignored |
||||
* @param options are ignored |
||||
*/ |
||||
public void initialize(Subject subject, CallbackHandler callbackHandler, |
||||
Map sharedState, Map options) { |
||||
this.subject = subject; |
||||
} |
||||
|
||||
/** |
||||
* Authenticate the <code>Subject</code> (phase one) by extracting the |
||||
* Acegi Security <code>Authentication</code> from the current |
||||
* <code>SecureContext</code>. |
||||
* |
||||
* @return true if the authentication succeeded, or false if this |
||||
* <code>LoginModule</code> should be ignored. |
||||
* |
||||
* @throws LoginException if the authentication fails |
||||
*/ |
||||
public boolean login() throws LoginException { |
||||
if (ContextHolder.getContext() == null) { |
||||
log.debug("no security context found"); |
||||
return false; |
||||
} |
||||
|
||||
if (!(ContextHolder.getContext() instanceof SecureContext)) { |
||||
log.debug("security context not instance of SecureContext"); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
SecureContext context = (SecureContext) ContextHolder.getContext(); |
||||
authen = context.getAuthentication(); |
||||
|
||||
if (authen == null) { |
||||
throw new LoginException("Authentication not found in security" |
||||
+ " context"); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Log out the <code>Subject</code>. |
||||
* |
||||
* @return true if this method succeeded, or false if this |
||||
* <code>LoginModule</code> should be ignored. |
||||
* |
||||
* @exception LoginException if the logout fails |
||||
*/ |
||||
public boolean logout() throws LoginException { |
||||
if (authen == null) { |
||||
return false; |
||||
} |
||||
|
||||
subject.getPrincipals().remove(authen); |
||||
authen = null; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Authentication getAuthentication() { |
||||
return authen; |
||||
} |
||||
|
||||
Subject getSubject() { |
||||
return subject; |
||||
} |
||||
} |
||||
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
/* Copyright 2004, 2005 Acegi Technology Pty Limited |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package net.sf.acegisecurity.providers.jaas; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import net.sf.acegisecurity.context.ContextHolder; |
||||
import net.sf.acegisecurity.context.ContextImpl; |
||||
import net.sf.acegisecurity.context.security.SecureContextImpl; |
||||
import net.sf.acegisecurity.context.security.SecureContext; |
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; |
||||
|
||||
import java.util.HashSet; |
||||
|
||||
import javax.security.auth.Subject; |
||||
import javax.security.auth.login.LoginException; |
||||
|
||||
|
||||
/** |
||||
* DOCUMENT ME! |
||||
* |
||||
* @author Ray Krueger |
||||
*/ |
||||
public class SecureContextLoginModuleTest extends TestCase { |
||||
//~ Instance fields ========================================================
|
||||
|
||||
private SecureContextLoginModule module = null; |
||||
private Subject subject = new Subject(false, new HashSet(), new HashSet(), |
||||
new HashSet()); |
||||
private UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("principal", "credentials"); |
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void testLoginException() throws Exception { |
||||
try { |
||||
module.login(); |
||||
fail("LoginException expected, there is no Authentication in the SecureContext"); |
||||
} catch (LoginException e) { |
||||
} |
||||
} |
||||
|
||||
public void testLoginSuccess() throws Exception { |
||||
SecureContext sc = (SecureContext) ContextHolder.getContext(); |
||||
sc.setAuthentication(auth); |
||||
assertTrue("Login should succeed, there is an authentication set", module.login()); |
||||
assertTrue("The authentication is not null, this should return true", module.commit()); |
||||
assertTrue("Principals should contain the authentication", subject.getPrincipals().contains(auth)); |
||||
} |
||||
|
||||
public void testNoContext() throws Exception { |
||||
ContextHolder.setContext(null); |
||||
assertFalse("Should return false and ask to be ignored", module.login()); |
||||
} |
||||
|
||||
public void testUnsupportedContext() throws Exception { |
||||
ContextHolder.setContext(new ContextImpl()); |
||||
assertFalse("Should return false and ask to be ignored", module.login()); |
||||
} |
||||
|
||||
public void testLogout() throws Exception { |
||||
SecureContext sc = (SecureContext) ContextHolder.getContext(); |
||||
sc.setAuthentication(auth); |
||||
module.login(); |
||||
assertTrue("Should return true as it succeeds", module.logout()); |
||||
assertEquals("Authentication should be null", null, module.getAuthentication()); |
||||
|
||||
assertFalse("Principals should not contain the authentication after logout", subject.getPrincipals().contains(auth)); |
||||
} |
||||
|
||||
public void testNullLogout() throws Exception { |
||||
assertFalse(module.logout()); |
||||
} |
||||
|
||||
public void testAbort() throws Exception { |
||||
assertFalse("Should return false, no auth is set", module.abort()); |
||||
SecureContext sc = (SecureContext) ContextHolder.getContext(); |
||||
sc.setAuthentication(auth); |
||||
module.login(); |
||||
module.commit(); |
||||
assertTrue(module.abort()); |
||||
} |
||||
|
||||
protected void setUp() throws Exception { |
||||
module = new SecureContextLoginModule(); |
||||
|
||||
module.initialize(subject, null, null, null); |
||||
|
||||
ContextHolder.setContext(new SecureContextImpl()); |
||||
} |
||||
|
||||
protected void tearDown() throws Exception { |
||||
ContextHolder.setContext(null); |
||||
module = null; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue