SecureContextLoginModule as requested from list with Test
This commit is contained in:
parent
6f286e2054
commit
2c23c75f91
|
@ -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 @@
|
||||||
|
/* 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