SEC-8: Introduction into CVS of contribution posted with the JIRA task and basic reformatting.
This commit is contained in:
parent
e9b1d9452f
commit
eae6f81177
|
@ -63,5 +63,6 @@
|
|||
<classpathentry kind="src" path="samples/annotations/src/main/resources"/>
|
||||
<classpathentry kind="src" path="samples/annotations/src/test/java"/>
|
||||
<classpathentry kind="src" path="samples/contacts-tiger/src/main/java"/>
|
||||
<classpathentry kind="var" path="MAVEN_REPO/jcifs/jars/jcifs-1.2.6.jar"/>
|
||||
<classpathentry kind="output" path="target/eclipseclasses"/>
|
||||
</classpath>
|
||||
|
|
|
@ -310,6 +310,13 @@
|
|||
<war.bundle>true</war.bundle>
|
||||
</properties>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jcifs</groupId>
|
||||
<artifactId>jcifs</artifactId>
|
||||
<version>1.2.6</version>
|
||||
<type>jar</type>
|
||||
<url>http://jcifs.samba.org/</url>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/* 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.smb;
|
||||
|
||||
import jcifs.UniAddress;
|
||||
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
import jcifs.smb.SmbAuthException;
|
||||
import jcifs.smb.SmbException;
|
||||
import jcifs.smb.SmbSession;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.AuthenticationException;
|
||||
import net.sf.acegisecurity.AuthenticationServiceException;
|
||||
import net.sf.acegisecurity.BadCredentialsException;
|
||||
import net.sf.acegisecurity.providers.AuthenticationProvider;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationProvider} implementation that relies on <a
|
||||
* href="http://www.jcifs.org">jcifs</a> in order to provide an authentication
|
||||
* service on a Windows network. This implementation relies on a {@link
|
||||
* #setAuthorizationProvider(AuthenticationProvider) delegate provider} in
|
||||
* order for authorization information to be filled into the authorized {@link
|
||||
* Authentication token}. Subclasses must implement the logic that {@link
|
||||
* #getNtlmPasswordAuthentication(Authentication) extracts the jcifs }{@link
|
||||
* NtlmPasswordAuthentication } object from the particular {@link
|
||||
* Authentication } token implementation and the one that {@link
|
||||
* #getDomainController(Authentication, NtlmPasswordAuthentication) extracts
|
||||
* the domain controller address }.
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AbstractSmbAuthenticationProvider
|
||||
implements AuthenticationProvider {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AuthenticationProvider authorizationProvider;
|
||||
private Log log = LogFactory.getLog(this.getClass());
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param authorizationProvider The {@link AuthenticationProvider } which
|
||||
* will be contacted in order for it to fill authorization info in
|
||||
* the (already authenticated) {@link Authentication } object that
|
||||
* they will be passed.
|
||||
*/
|
||||
public void setAuthorizationProvider(
|
||||
AuthenticationProvider authorizationProvider) {
|
||||
this.authorizationProvider = authorizationProvider;
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
NtlmPasswordAuthentication ntlm = getNtlmPasswordAuthentication(authentication);
|
||||
UniAddress dc = getDomainController(authentication, ntlm);
|
||||
|
||||
return performAuthentication(dc, ntlm, authentication);
|
||||
}
|
||||
|
||||
protected abstract UniAddress getDomainController(
|
||||
Authentication authentication,
|
||||
NtlmPasswordAuthentication ntlmAuthentication);
|
||||
|
||||
protected abstract NtlmPasswordAuthentication getNtlmPasswordAuthentication(
|
||||
Authentication authentication);
|
||||
|
||||
protected Authentication performAuthentication(UniAddress dc,
|
||||
NtlmPasswordAuthentication ntlm, Authentication authentication) {
|
||||
try {
|
||||
// this performs authentication...
|
||||
SmbSession.logon(dc, ntlm);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(ntlm + " successfully authenticated against " + dc);
|
||||
}
|
||||
|
||||
// ...and this performs authorization.
|
||||
Authentication authorizedResult = authorizationProvider
|
||||
.authenticate(authentication);
|
||||
|
||||
return authorizedResult;
|
||||
} catch (SmbException se) {
|
||||
log.error(ntlm.getName() + ": 0x"
|
||||
+ jcifs.util.Hexdump.toHexString(se.getNtStatus(), 8) + ": "
|
||||
+ se);
|
||||
|
||||
if (se instanceof SmbAuthException) {
|
||||
SmbAuthException sae = (SmbAuthException) se;
|
||||
|
||||
if (se.getNtStatus() == SmbAuthException.NT_STATUS_ACCESS_VIOLATION) {
|
||||
throw new ChallengeExpiredException(sae.getMessage(), sae);
|
||||
} else {
|
||||
throw new BadCredentialsException(sae.getMessage(), sae);
|
||||
}
|
||||
} else {
|
||||
throw new AuthenticationServiceException(se.getMessage(), se);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* 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.smb;
|
||||
|
||||
import net.sf.acegisecurity.AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown if
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ChallengeExpiredException extends AuthenticationException {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public ChallengeExpiredException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public ChallengeExpiredException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/* 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.smb;
|
||||
|
||||
import jcifs.UniAddress;
|
||||
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* {@link Authentication } implementation for NTLM smb authentication.
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*
|
||||
* @see net.sf.acegisecurity.ui.ntlm.NtlmProcessingFilter
|
||||
* @see net.sf.acegisecurity.providers.smb.SmbNtlmAuthenticationProvider
|
||||
*/
|
||||
public class NtlmAuthenticationToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private NtlmPasswordAuthentication ntlmPasswordAuthentication;
|
||||
private transient UniAddress domainController;
|
||||
private GrantedAuthority[] authorities;
|
||||
private boolean authenticated;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public NtlmAuthenticationToken(
|
||||
NtlmPasswordAuthentication ntlmPasswordAuthentication,
|
||||
UniAddress domainController) {
|
||||
this.ntlmPasswordAuthentication = ntlmPasswordAuthentication;
|
||||
this.domainController = domainController;
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAuthenticated(boolean isAuthenticated) {
|
||||
this.authenticated = isAuthenticated;
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
public void setAuthorities(GrantedAuthority[] authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
public GrantedAuthority[] getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public Object getCredentials() {
|
||||
return ntlmPasswordAuthentication.getPassword();
|
||||
}
|
||||
|
||||
public UniAddress getDomainController() {
|
||||
return domainController;
|
||||
}
|
||||
|
||||
public NtlmPasswordAuthentication getNtlmPasswordAuthentication() {
|
||||
return ntlmPasswordAuthentication;
|
||||
}
|
||||
|
||||
public Object getPrincipal() {
|
||||
return ntlmPasswordAuthentication.getUsername();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/* 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.smb;
|
||||
|
||||
import jcifs.Config;
|
||||
import jcifs.UniAddress;
|
||||
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.BadCredentialsException;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
||||
/**
|
||||
* Provides authentication of a basic {@link
|
||||
* UsernamePasswordAuthenticationToken } on a ntlm domain via smb/cifs.
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SmbBasicAuthenticationProvider
|
||||
extends AbstractSmbAuthenticationProvider {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
String domainController;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setDomainController(String domainController) {
|
||||
this.domainController = domainController;
|
||||
}
|
||||
|
||||
public boolean supports(Class authentication) {
|
||||
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
protected UniAddress getDomainController(Authentication authentication,
|
||||
NtlmPasswordAuthentication ntlmAuthentication) {
|
||||
try {
|
||||
if (domainController == null) {
|
||||
domainController = Config.getProperty("jcifs.smb.client.domain");
|
||||
}
|
||||
|
||||
String domain = domainController;
|
||||
|
||||
if (domain == null) {
|
||||
domain = ntlmAuthentication.getDomain();
|
||||
}
|
||||
|
||||
UniAddress dc = UniAddress.getByName(domain, true);
|
||||
|
||||
return dc;
|
||||
} catch (UnknownHostException uhe) {
|
||||
throw new BadCredentialsException(
|
||||
"no host could be found for the name "
|
||||
+ ntlmAuthentication.getDomain(), uhe);
|
||||
}
|
||||
}
|
||||
|
||||
protected NtlmPasswordAuthentication getNtlmPasswordAuthentication(
|
||||
Authentication authentication) {
|
||||
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
|
||||
String username = token.getPrincipal().toString();
|
||||
String password = (String) token.getCredentials();
|
||||
int index = username.indexOf('\\');
|
||||
|
||||
if (index == -1) {
|
||||
index = username.indexOf('/');
|
||||
}
|
||||
|
||||
// if domain is null then the jcifs default is used
|
||||
// (this is set through the "jcifs.smb.client.domain" Config property)
|
||||
String domain = (index != -1) ? username.substring(0, index) : null;
|
||||
username = (index != -1) ? username.substring(index + 1) : username;
|
||||
|
||||
NtlmPasswordAuthentication ntlm = new NtlmPasswordAuthentication(domain,
|
||||
username, password);
|
||||
|
||||
return ntlm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* 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.smb;
|
||||
|
||||
import jcifs.UniAddress;
|
||||
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ui.ntlm.NtlmProcessingFilter;
|
||||
|
||||
|
||||
/**
|
||||
* This class provides authentication through smb of {@link
|
||||
* NtlmAuthenticationToken } (i.e. tokens obtained through the NTLM
|
||||
* Authorization method by {@link NtlmProcessingFilter } ).
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*
|
||||
* @see net.sf.acegisecurity.ui.ntlm.NtlmProcessingFilter
|
||||
*/
|
||||
public class SmbNtlmAuthenticationProvider
|
||||
extends AbstractSmbAuthenticationProvider {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(Class authentication) {
|
||||
return NtlmAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
protected UniAddress getDomainController(Authentication authentication,
|
||||
NtlmPasswordAuthentication ntlmAuthentication) {
|
||||
NtlmAuthenticationToken ntlmToken = (NtlmAuthenticationToken) authentication;
|
||||
UniAddress dc = ntlmToken.getDomainController();
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
protected NtlmPasswordAuthentication getNtlmPasswordAuthentication(
|
||||
Authentication authentication) {
|
||||
NtlmAuthenticationToken ntlmToken = (NtlmAuthenticationToken) authentication;
|
||||
NtlmPasswordAuthentication ntlm = ntlmToken
|
||||
.getNtlmPasswordAuthentication();
|
||||
|
||||
return ntlm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* LICENSE IS UNKNOWN (SEE TODO COMMENT LATER IN SOURCE CODE)
|
||||
*/
|
||||
package net.sf.acegisecurity.ui.ntlm;
|
||||
|
||||
import jcifs.Config;
|
||||
import jcifs.UniAddress;
|
||||
|
||||
import jcifs.http.NtlmSsp;
|
||||
|
||||
import jcifs.smb.NtlmChallenge;
|
||||
import jcifs.smb.NtlmPasswordAuthentication;
|
||||
import jcifs.smb.SmbSession;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.AuthenticationException;
|
||||
import net.sf.acegisecurity.AuthenticationManager;
|
||||
import net.sf.acegisecurity.BadCredentialsException;
|
||||
import net.sf.acegisecurity.context.SecurityContextHolder;
|
||||
import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint;
|
||||
import net.sf.acegisecurity.providers.smb.NtlmAuthenticationToken;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
/**
|
||||
* A reimplementation of the jcifs NtlmHttpFilter suitable for use with the
|
||||
* Acegi Security System.
|
||||
*
|
||||
* <p>
|
||||
* This servlet Filter can be used to negotiate password hashes with MSIE
|
||||
* clients using NTLM SSP. This is similar to <code>Authentication:
|
||||
* BASIC</code> but weakly encrypted and without requiring the user to
|
||||
* re-supply authentication credentials.
|
||||
* </p>
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NtlmProcessingFilter implements Filter, InitializingBean {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final String CHALLENGE_ATTR_NAME = "NtlmHttpChal";
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
// TODO: Verify licensing, as original contributor reported that large parts of this code where taken from jCifs NtmlHttpFilter: can this be re-licensed to APL (?).
|
||||
private Log log = LogFactory.getLog(this.getClass());
|
||||
private String defaultDomain;
|
||||
private String domainController;
|
||||
private boolean loadBalance;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param authenticationEntryPoint The entry point that will be called if
|
||||
* the "transparent" authentication fails for some reason: don't
|
||||
* use the same {@link NtlmProcessingFilterEntryPoint} that is used
|
||||
* in order to commence the NTLM authentication or the user's
|
||||
* browser would probably loop
|
||||
*/
|
||||
public void setAuthenticationEntryPoint(
|
||||
AuthenticationEntryPoint authenticationEntryPoint) {
|
||||
this.authenticationEntryPoint = authenticationEntryPoint;
|
||||
}
|
||||
|
||||
public void setAuthenticationManager(
|
||||
AuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param defaultDomain The domain that will be specified as part of the
|
||||
* authentication credentials if not specified by the username.
|
||||
*/
|
||||
public void setDefaultDomain(String defaultDomain) {
|
||||
this.defaultDomain = defaultDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param domainController The domain controller address: if not set the
|
||||
* default domain is used.
|
||||
*/
|
||||
public void setDomainController(String domainController) {
|
||||
this.domainController = domainController;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param properties A {@link Properties} object whose properties with
|
||||
* names starting with "jcifs." will be set into the jCifs {@link
|
||||
* Config}.
|
||||
*/
|
||||
public void setJCifsProperties(Properties properties) {
|
||||
for (Iterator iterator = properties.keySet().iterator();
|
||||
iterator.hasNext();) {
|
||||
String propertyName = (String) iterator.next();
|
||||
String propertyValue = properties.getProperty(propertyName);
|
||||
|
||||
if (propertyName.startsWith("jcifs.")) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("setting jcifs property " + propertyName + ":"
|
||||
+ propertyValue);
|
||||
}
|
||||
|
||||
Config.setProperty(propertyName, propertyValue);
|
||||
} else {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("ignoring non-jcifs property " + propertyName
|
||||
+ ":" + propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoadBalance(boolean loadBalance) {
|
||||
this.loadBalance = loadBalance;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// Set jcifs properties we know we want; soTimeout and cachePolicy to 10min
|
||||
Config.setProperty("jcifs.smb.client.soTimeout", "300000");
|
||||
Config.setProperty("jcifs.netbios.cachePolicy", "1200");
|
||||
|
||||
if (domainController == null) {
|
||||
domainController = defaultDomain;
|
||||
}
|
||||
|
||||
if (defaultDomain != null) {
|
||||
Config.setProperty("jcifs.smb.client.domain", defaultDomain);
|
||||
}
|
||||
|
||||
Assert.notNull(authenticationEntryPoint,
|
||||
"The authenticationEntryPoint property must be set before "
|
||||
+ "NtlmProcessingFilter bean initialization");
|
||||
Assert.notNull(authenticationManager,
|
||||
"The authenticationManager property must be set before "
|
||||
+ "NtlmProcessingFilter bean initialization");
|
||||
}
|
||||
|
||||
public void destroy() {}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
NtlmPasswordAuthentication ntlm = null;
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
|
||||
try {
|
||||
String msg = req.getHeader("Authorization");
|
||||
|
||||
UniAddress dc = null;
|
||||
|
||||
// the "basic" authentication case (both secure + insecure) originally in jcifs NtlmFilter has been
|
||||
// refactored out, in order for it to be supported by the acegi BasicProcessingFilter +
|
||||
// SmbNtlmAuthenticationProvider ( + SecureChannelProcessor) combination */
|
||||
if ((msg != null) && (msg.startsWith("NTLM "))) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("NTLM Authorization header received");
|
||||
}
|
||||
|
||||
HttpSession ssn = req.getSession();
|
||||
byte[] challenge;
|
||||
|
||||
if (loadBalance) {
|
||||
NtlmChallenge chal = (NtlmChallenge) ssn.getAttribute(CHALLENGE_ATTR_NAME);
|
||||
|
||||
if (chal == null) {
|
||||
chal = SmbSession.getChallengeForDomain();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"got load balanced challenge for domain: "
|
||||
+ chal);
|
||||
}
|
||||
|
||||
ssn.setAttribute(CHALLENGE_ATTR_NAME, chal);
|
||||
}
|
||||
|
||||
dc = chal.dc;
|
||||
challenge = chal.challenge;
|
||||
} else {
|
||||
// no challenge in session, here: the server itself keeps the challenge alive for a certain time
|
||||
dc = UniAddress.getByName(domainController, true);
|
||||
challenge = SmbSession.getChallenge(dc);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("domain controller is " + dc
|
||||
+ ", challenge is " + challenge);
|
||||
}
|
||||
}
|
||||
|
||||
ntlm = NtlmSsp.authenticate(req, resp, challenge);
|
||||
|
||||
if (ntlm == null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"null ntlm authentication results: sending challenge to browser");
|
||||
}
|
||||
|
||||
return; // this means we must send the challenge to the browser
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ntlm negotiation complete");
|
||||
}
|
||||
|
||||
ssn.removeAttribute(CHALLENGE_ATTR_NAME); /* negotiation complete, remove the challenge object */
|
||||
}
|
||||
|
||||
NtlmAuthenticationToken ntlmToken = newNtlmAuthenticationToken(ntlm,
|
||||
dc);
|
||||
Authentication authResult = authenticationManager.authenticate(ntlmToken);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("ntlm token authenticated ");
|
||||
}
|
||||
|
||||
successfulAuthentication(req, resp, authResult);
|
||||
}
|
||||
} catch (AuthenticationException ae) {
|
||||
unsuccessfulAuthentication(req, resp, ntlm, ae);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {}
|
||||
|
||||
protected NtlmAuthenticationToken newNtlmAuthenticationToken(
|
||||
NtlmPasswordAuthentication ntlm, UniAddress dc) {
|
||||
return new NtlmAuthenticationToken(ntlm, dc);
|
||||
}
|
||||
|
||||
protected void successfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authResult) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Authentication success: " + authResult.toString());
|
||||
}
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authResult);
|
||||
}
|
||||
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest req,
|
||||
HttpServletResponse resp, NtlmPasswordAuthentication ntlm,
|
||||
AuthenticationException ae) throws IOException, ServletException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Authentication request for user: " + ntlm.getUsername()
|
||||
+ " failed: " + ae.toString());
|
||||
}
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
authenticationEntryPoint.commence(req, resp,
|
||||
new BadCredentialsException(ae.getMessage(), ae));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* 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.ui.ntlm;
|
||||
|
||||
import net.sf.acegisecurity.AuthenticationException;
|
||||
import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* An entry point for the NTLM authentication process.
|
||||
*
|
||||
* @author Davide Baroncelli
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NtlmProcessingFilterEntryPoint implements AuthenticationEntryPoint {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void commence(ServletRequest request, ServletResponse response,
|
||||
AuthenticationException authException)
|
||||
throws IOException, ServletException {
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
resp.setHeader("WWW-Authenticate", "NTLM");
|
||||
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED,
|
||||
(authException != null) ? authException.getMessage() : "");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue