SES-1: Added KerberosServiceAuthenticationProvider

This commit is contained in:
Mike Wiesner
2009-08-25 19:22:33 +00:00
parent a42a19ef42
commit e4e888f106
4 changed files with 168 additions and 1 deletions

View File

@@ -0,0 +1,38 @@
package org.springframework.security.extensions.kerberos;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
public class KerberosServiceAuthenticationProvider implements
AuthenticationProvider {
private KerberosTicketValidator ticketValidator;
private UserDetailsService userDetailsService;
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public void setTicketValidator(KerberosTicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
KerberosServiceRequestToken auth = (KerberosServiceRequestToken) authentication;
byte[] token = auth.getToken();
String username = this.ticketValidator.validateTicket(token);
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
return new KerberosServiceRequestToken(userDetails, userDetails.getAuthorities(), token);
}
@Override
public boolean supports(Class<? extends Object> auth) {
return KerberosServiceRequestToken.class.isAssignableFrom(auth);
}
}

View File

@@ -16,7 +16,10 @@
package org.springframework.security.extensions.kerberos;
import java.util.List;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
/**
* Holds the Kerberos/SPNEGO token for requesting a kerberized service Will
@@ -30,9 +33,15 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
public class KerberosServiceRequestToken extends AbstractAuthenticationToken {
public KerberosServiceRequestToken(Object principal, List<GrantedAuthority> authorities, byte[] token) {
super(authorities);
this.token = token;
this.principal = principal;
}
private static final long serialVersionUID = 395488921064775014L;
private final byte[] token;
private final Object principal = null;
private final Object principal;
/**
* Creates an unauthenticated instance which should then be authenticated by
@@ -44,6 +53,7 @@ public class KerberosServiceRequestToken extends AbstractAuthenticationToken {
public KerberosServiceRequestToken(byte[] token) {
super(null);
this.token = token;
this.principal = null;
}
@Override

View File

@@ -0,0 +1,7 @@
package org.springframework.security.extensions.kerberos;
public interface KerberosTicketValidator {
public abstract String validateTicket(byte[] token);
}

View File

@@ -0,0 +1,112 @@
package org.springframework.security.extensions.kerberos;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.util.Assert;
public class SunJaasKerberosTicketValidator implements KerberosTicketValidator, InitializingBean {
private String servicePrincipal;
private Resource keyTabLocation;
private Subject serviceSubject;
public String validateTicket(byte[] token) {
String username = null;
try {
username = Subject.doAs(this.serviceSubject, new KerberosValidateAction(token));
} catch (PrivilegedActionException e) {
throw new BadCredentialsException("Kerberos validation not succesfull", e);
}
return username;
}
public void setServicePrincipal(String servicePrincipal) {
this.servicePrincipal = servicePrincipal;
}
public void setKeyTabLocation(Resource keyTabLocation) {
this.keyTabLocation = keyTabLocation;
}
public void setServiceSubject(Subject serviceSubject) {
this.serviceSubject = serviceSubject;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.servicePrincipal, "ServicePrincipal muss gesetzt werden");
Assert.notNull(this.keyTabLocation, "KeyTab muss gesetzt werden");
LoginConfig loginConfig = new LoginConfig(this.keyTabLocation.getURL().toExternalForm(), servicePrincipal);
Set<Principal> princ = new HashSet<Principal>(1);
princ.add(new KerberosPrincipal(this.servicePrincipal));
Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
LoginContext lc = new LoginContext("", sub, null, loginConfig);
lc.login();
this.serviceSubject = lc.getSubject();
}
private static class KerberosValidateAction implements PrivilegedExceptionAction<String> {
byte[] kerberosTicket;
public KerberosValidateAction(byte[] kerberosTicket) {
this.kerberosTicket = kerberosTicket;
}
@Override
public String run() throws Exception {
GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null);
context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length);
String user = context.getSrcName().toString();
context.dispose();
return user;
}
}
private static class LoginConfig extends Configuration {
private String keyTabLocation;
private String servicePrincipalName;
public LoginConfig(String keyTabLocation, String servicePrincipalName) {
this.keyTabLocation = keyTabLocation;
this.servicePrincipalName = servicePrincipalName;
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
HashMap<String, String> options = new HashMap<String, String>();
options.put("useKeyTab", "true");
options.put("keyTab", this.keyTabLocation);
options.put("principal", this.servicePrincipalName);
options.put("storeKey", "true");
options.put("doNotPrompt", "true");
options.put("debug", "true");
options.put("isInitiator", "false");
return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), };
}
}
}