SecureContextLoginModule as requested from list with Test

This commit is contained in:
Ray Krueger 2005-04-27 04:47:41 +00:00
parent 6f286e2054
commit 2c23c75f91
2 changed files with 282 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}