Commit ab7379bb authored by Misagh Moayyed's avatar Misagh Moayyed
Browse files

SPNEGO client config automated

parent ccccc4b7
...@@ -128,10 +128,12 @@ Then verify that your are able to read the keytab file: ...@@ -128,10 +128,12 @@ Then verify that your are able to read the keytab file:
* Internet Explorer - Enable _Integrated Windows Authentication_ and add the CAS server URL to the _Local Intranet_ * Internet Explorer - Enable _Integrated Windows Authentication_ and add the CAS server URL to the _Local Intranet_
zone. zone.
* Firefox - Set the `network.negotiate-auth.trusted-uris` configuration parameter in `about:config` to the CAS server * Firefox - Set the `network.negotiate-auth.trusted-uris` configuration parameter in `about:config` to the CAS server
URL, e.g. https://cas.example.com. URL, e.g. `https://cas.example.com`.
### CAS Component Configuration ### Configuration
####Webflow Configuration
Define two new action states in `login-webflow.xml` before the `viewLoginForm` state: Define two new action states in `login-webflow.xml` before the `viewLoginForm` state:
{% highlight xml %} {% highlight xml %}
...@@ -149,33 +151,27 @@ Define two new action states in `login-webflow.xml` before the `viewLoginForm` s ...@@ -149,33 +151,27 @@ Define two new action states in `login-webflow.xml` before the `viewLoginForm` s
Additionally, find action `generateLoginTicket` - replace `viewLoginForm` with `startAuthenticate`. Additionally, find action `generateLoginTicket` - replace `viewLoginForm` with `startAuthenticate`.
Add two bean definitions in `cas-servlet.xml`: Insert the appropriate action before SPNEGO initiation, assigning a `yes` response route to SPNEGO,
and a `no` response to route to viewing the login form.
{% highlight xml %} {% highlight xml %}
<bean id="negociateSpnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoNegociateCredentialsAction" /> <action-state id="eveluateClientRequest">
<evaluate expression="hostnameSpnegoClientAction" />
<bean id="spnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoCredentialsAction" <transition on="yes" to="startAuthenticate" />
p:centralAuthenticationService-ref="centralAuthenticationService" /> <transition on="no" to="generateLoginTicket" />
</action-state>
{% endhighlight %} {% endhighlight %}
####Authentication Configuration
Update `deployerConfigContext.xml` according to the following template: Update `deployerConfigContext.xml` according to the following template:
{% highlight xml %} {% highlight xml %}
<bean id="jcifsConfig"
class="org.jasig.cas.support.spnego.authentication.handler.support.JcifsConfig"
p:jcifsServicePrincipal="HTTP/cas.example.com@EXAMPLE.COM"
p:kerberosDebug="false"
p:kerberosRealm="EXAMPLE.COM"
p:kerberosKdc="172.10.1.10"
p:loginConf="/path/to/login.conf" />
<bean id="spnegoAuthentication" class="jcifs.spnego.Authentication" />
<bean id="spnegoHandler" <bean id="spnegoHandler"
class="org.jasig.cas.support.spnego.authentication.handler.support.JcifsSpnegoAuthenticationHandler" class="org.jasig.cas.support.spnego.authentication.handler.support.JcifsSpnegoAuthenticationHandler"
p:authentication-ref="spnegoAuthentication" p:authentication-ref="spnegoAuthentication"
p:principalWithDomainName="false" p:principalWithDomainName="${cas.spengo.use.principal.domain:false}"
p:NTLMallowed="true" /> p:NTLMallowed="${cas.spnego.ntlm.allowed:true}" />
<bean id="spnegoPrincipalResolver" <bean id="spnegoPrincipalResolver"
class="org.jasig.cas.support.spnego.authentication.principal.SpnegoPrincipalResolver" /> class="org.jasig.cas.support.spnego.authentication.principal.SpnegoPrincipalResolver" />
...@@ -195,8 +191,7 @@ Update `deployerConfigContext.xml` according to the following template: ...@@ -195,8 +191,7 @@ Update `deployerConfigContext.xml` according to the following template:
</bean> </bean>
{% endhighlight %} {% endhighlight %}
Provide a JAAS `login.conf` file in a location that agrees with the `loginConf` property of the `JCIFSConfig` bean Provide a JAAS `login.conf` file:
above.
jcifs.spnego.initiate { jcifs.spnego.initiate {
com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab"; com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab";
...@@ -205,67 +200,79 @@ above. ...@@ -205,67 +200,79 @@ above.
com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab"; com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true keyTab="/home/cas/kerberos/myspnaccount.keytab";
}; };
## Client Selection Strategy You may use the following configuration in `cas.properties`:
CAS provides a set of components that attempt to activate the SPNEGO flow conditionally, in case deployers need a configurable way to decide whether SPNEGO should be applied to the current authentication/browser request. The components provided are webflow actions that return either `yes` or `no` to the webflow and allow you to reroute the webflow conditionally based the outcome, to either SPNEGO or the normal CAS login flow.
{% highlight properties %}
# cas.spnego.ldap.attribute=spnegoattribute
# cas.spnego.ldap.filter=host={0}
# cas.spnego.ldap.basedn=
# cas.spnego.hostname.pattern=.+
# cas.spnego.ip.pattern=
# cas.spnego.alt.remote.host.attribute
# cas.spengo.use.principal.domain=false
# cas.spnego.ntlm.allowed=true
# cas.spnego.kerb.debug=false
# cas.spnego.kerb.realm=EXAMPLE.COM
# cas.spnego.kerb.kdc=172.10.1.10
# cas.spnego.login.conf.file=/path/to/login.conf
# cas.spnego.jcifs.domain=
# cas.spnego.jcifs.domaincontroller=
# cas.spnego.jcifs.netbios.cache.policy:600
# cas.spnego.jcifs.netbios.wins=
# cas.spnego.jcifs.password=
# cas.spnego.jcifs.service.password=
# cas.spnego.jcifs.socket.timeout:300000
# cas.spnego.jcifs.username=
# cas.spnego.kerb.conf=
# cas.spnego.ntlm=false
# cas.spnego.supportedBrowsers=MSIE,Trident,Firefox,AppleWebKit
# cas.spnego.mixed.mode.authn=false
# cas.spnego.send.401.authn.failure=false
{% endhighlight %}
The activation strategies are as follows: ## Client Selection Strategy
CAS provides a set of components that attempt to activate the SPNEGO flow conditionally,
in case deployers need a configurable way to decide whether SPNEGO should be applied to the
current authentication/browser request.
### By Remote IP ### By Remote IP
Checks to see if the request's remote ip address matches a predefine pattern. Checks to see if the request's remote ip address matches a predefine pattern.
```xml {% highlight xml %}
<bean id="baseSpnegoClientAction" ...
class="org.jasig.cas.support.spnego.web.flow.client.BaseSpnegoKnownClientSystemsFilterAction" <evaluate expression="baseSpnegoClientAction" />
c:ipsToCheckPattern="127.+" ...
c:alternativeRemoteHostAttribute="alternateRemoteHeader" /> {% endhighlight %}
```
### By Hostname ### By Hostname
Checks to see if the request's remote hostname matches a predefine pattern. This action supports all functionality provided by `BaseSpnegoKnownClientSystemsFilterAction`. Checks to see if the request's remote hostname matches a predefine pattern.
```xml {% highlight xml %}
<bean id="hostnameSpnegoClientAction" ...
class="org.jasig.cas.support.spnego.web.flow.client.HostNameSpnegoKnownClientSystemsFilterAction" <evaluate expression="hostnameSpnegoClientAction" />
c:hostNamePatternString="something.+" /> ...
``` {% endhighlight %}
### By LDAP Attribute ### By LDAP Attribute
Checks an LDAP instance for the remote hostname, to locate a pre-defined attribute whose mere existence would allow the webflow to resume to SPNEGO. This action supports all functionality provided by `BaseSpnegoKnownClientSystemsFilterAction`. Checks an LDAP instance for the remote hostname, to locate a pre-defined attribute whose mere existence
would allow the webflow to resume to SPNEGO.
```xml {% highlight xml %}
<bean id="ldapSpnegoClientAction" <bean id="ldapSpnegoClientAction"
class="org.jasig.cas.support.spnego.web.flow.client.LdapSpnegoKnownClientSystemsFilterAction" class="org.jasig.cas.support.spnego.web.flow.client.LdapSpnegoKnownClientSystemsFilterAction"
c:connectionFactory-ref="connectionFactory" c:connectionFactory-ref="connectionFactory"
c:searchRequest-ref="searchRequest" c:searchRequest-ref="searchRequest"
c:spnegoAttributeName="spnegoAttribute" /> c:spnegoAttributeName="${cas.spnego.ldap.attribute:spnegoAttribute}" />
```
Sample search request and filer:
```xml
<bean id="searchRequest" class="org.ldaptive.SearchRequest" <bean id="searchRequest" class="org.ldaptive.SearchRequest"
p:baseDn-ref="baseDn" p:baseDn-ref="baseDn"
p:searchFilter-ref="searchFilter"/> p:searchFilter-ref="searchFilter"/>
<bean id="searchFilter" class="org.ldaptive.SearchFilter" <bean id="searchFilter" class="org.ldaptive.SearchFilter"
c:filter="host={0}" /> c:filter="${cas.spnego.ldap.filter:host={0}}" />
<bean id="baseDn" class="java.lang.String"> <bean id="baseDn" class="java.lang.String">
<constructor-arg type="java.lang.String" value="${ldap.baseDn}" /> <constructor-arg type="java.lang.String" value="${cas.spnego.ldap.basedn:}" />
</bean> </bean>
``` {% endhighlight %}
### Webflow Configuration
Insert the appropriate action before SPNEGO initiation, assigning a `yes` response route to SPNEGO, and a `no` response to route to viewing the login form.
```xml
<action-state id="eveluateClientRequest">
<evaluate expression="hostnameSpnegoClientAction" />
<transition on="yes" to="startAuthenticate" />
<transition on="no" to="generateLoginTicket" />
</action-state>
...
```
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.jasig.cas.support.spnego.authentication.handler.support; package org.jasig.cas.support.spnego.authentication.handler.support;
import jcifs.Config; import jcifs.Config;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
...@@ -59,6 +60,10 @@ public final class JcifsConfig implements InitializingBean { ...@@ -59,6 +60,10 @@ public final class JcifsConfig implements InitializingBean {
private static final String JCIFS_PROP_CLIENT_PASSWORD = "jcifs.smb.client.password"; private static final String JCIFS_PROP_CLIENT_PASSWORD = "jcifs.smb.client.password";
private static final String JCIFS_PROP_CLIENT_SOTIMEOUT = "jcifs.smb.client.soTimeout";
private static final String JCIFS_PROP_NETBIOS_CACHE_POLICY = "jcifs.netbios.cachePolicy";
/** /**
* -- the service principal you just created. Using the previous example, * -- the service principal you just created. Using the previous example,
* this would be "HTTP/mybox at DOMAIN.COM". * this would be "HTTP/mybox at DOMAIN.COM".
...@@ -80,15 +85,15 @@ public final class JcifsConfig implements InitializingBean { ...@@ -80,15 +85,15 @@ public final class JcifsConfig implements InitializingBean {
* Instantiates a new jCIFS config. * Instantiates a new jCIFS config.
*/ */
public JcifsConfig() { public JcifsConfig() {
Config.setProperty("jcifs.smb.client.soTimeout", "300000"); Config.setProperty(JCIFS_PROP_CLIENT_SOTIMEOUT, "300000");
Config.setProperty("jcifs.netbios.cachePolicy", "600"); Config.setProperty(JCIFS_PROP_NETBIOS_CACHE_POLICY, "600");
} }
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
final String propValue = System.getProperty(SYS_PROP_LOGIN_CONF); final String propValue = System.getProperty(SYS_PROP_LOGIN_CONF);
if (propValue != null) { if (propValue != null) {
logger.warn("found login config in system property, may overide : {}", propValue); logger.warn("found login config in system property, may override : {}", propValue);
} }
URL url = getClass().getResource( URL url = getClass().getResource(
...@@ -107,15 +112,19 @@ public final class JcifsConfig implements InitializingBean { ...@@ -107,15 +112,19 @@ public final class JcifsConfig implements InitializingBean {
logger.debug("configured login configuration path : {}", propValue); logger.debug("configured login configuration path : {}", propValue);
} }
/** /**
* Sets the jcifs service password. * Sets the jcifs service password.
* *
* @param jcifsServicePassword the new jcifs service password * @param jcifsServicePassword the new jcifs service password
*/ */
public void setJcifsServicePassword(final String jcifsServicePassword) { public void setJcifsServicePassword(final String jcifsServicePassword) {
if (StringUtils.isNotBlank(jcifsServicePassword)) {
logger.debug("jcifsServicePassword is set to *****"); logger.debug("jcifsServicePassword is set to *****");
Config.setProperty(JCIFS_PROP_SERVICE_PASSWORD, jcifsServicePassword); Config.setProperty(JCIFS_PROP_SERVICE_PASSWORD, jcifsServicePassword);
} }
}
/** /**
* Sets the jcifs service principal. * Sets the jcifs service principal.
...@@ -123,9 +132,11 @@ public final class JcifsConfig implements InitializingBean { ...@@ -123,9 +132,11 @@ public final class JcifsConfig implements InitializingBean {
* @param jcifsServicePrincipal the new jcifs service principal * @param jcifsServicePrincipal the new jcifs service principal
*/ */
public void setJcifsServicePrincipal(final String jcifsServicePrincipal) { public void setJcifsServicePrincipal(final String jcifsServicePrincipal) {
if (StringUtils.isNotBlank(jcifsServicePrincipal)) {
logger.debug("jcifsServicePrincipal is set to {}", jcifsServicePrincipal); logger.debug("jcifsServicePrincipal is set to {}", jcifsServicePrincipal);
Config.setProperty(JCIFS_PROP_SERVICE_PRINCIPAL, jcifsServicePrincipal); Config.setProperty(JCIFS_PROP_SERVICE_PRINCIPAL, jcifsServicePrincipal);
} }
}
/** /**
* Sets the kerberos conf. * Sets the kerberos conf.
...@@ -133,9 +144,12 @@ public final class JcifsConfig implements InitializingBean { ...@@ -133,9 +144,12 @@ public final class JcifsConfig implements InitializingBean {
* @param kerberosConf the new kerberos conf * @param kerberosConf the new kerberos conf
*/ */
public void setKerberosConf(final String kerberosConf) { public void setKerberosConf(final String kerberosConf) {
if (StringUtils.isNotBlank(kerberosConf)) {
logger.debug("kerberosConf is set to :{}", kerberosConf); logger.debug("kerberosConf is set to :{}", kerberosConf);
System.setProperty(SYS_PROP_KERBEROS_CONF, kerberosConf); System.setProperty(SYS_PROP_KERBEROS_CONF, kerberosConf);
} }
}
/** /**
* Sets the kerberos kdc. * Sets the kerberos kdc.
...@@ -143,9 +157,12 @@ public final class JcifsConfig implements InitializingBean { ...@@ -143,9 +157,12 @@ public final class JcifsConfig implements InitializingBean {
* @param kerberosKdc the new kerberos kdc * @param kerberosKdc the new kerberos kdc
*/ */
public void setKerberosKdc(final String kerberosKdc) { public void setKerberosKdc(final String kerberosKdc) {
if (StringUtils.isNotBlank(kerberosKdc)) {
logger.debug("kerberosKdc is set to : {}", kerberosKdc); logger.debug("kerberosKdc is set to : {}", kerberosKdc);
System.setProperty(SYS_PROP_KERBEROS_KDC, kerberosKdc); System.setProperty(SYS_PROP_KERBEROS_KDC, kerberosKdc);
} }
}
/** /**
* Sets the kerberos realm. * Sets the kerberos realm.
...@@ -153,9 +170,11 @@ public final class JcifsConfig implements InitializingBean { ...@@ -153,9 +170,11 @@ public final class JcifsConfig implements InitializingBean {
* @param kerberosRealm the new kerberos realm * @param kerberosRealm the new kerberos realm
*/ */
public void setKerberosRealm(final String kerberosRealm) { public void setKerberosRealm(final String kerberosRealm) {
if (StringUtils.isNotBlank(kerberosRealm)) {
logger.debug("kerberosRealm is set to :{}", kerberosRealm); logger.debug("kerberosRealm is set to :{}", kerberosRealm);
System.setProperty(SYS_PROP_KERBEROS_REALM, kerberosRealm); System.setProperty(SYS_PROP_KERBEROS_REALM, kerberosRealm);
} }
}
public void setLoginConf(final String loginConf) { public void setLoginConf(final String loginConf) {
this.loginConf = loginConf; this.loginConf = loginConf;
...@@ -177,47 +196,83 @@ public final class JcifsConfig implements InitializingBean { ...@@ -177,47 +196,83 @@ public final class JcifsConfig implements InitializingBean {
* @param kerberosDebug the new kerberos debug * @param kerberosDebug the new kerberos debug
*/ */
public void setKerberosDebug(final String kerberosDebug) { public void setKerberosDebug(final String kerberosDebug) {
if (StringUtils.isNotBlank(kerberosDebug)) {
logger.debug("kerberosDebug is set to : {}", kerberosDebug); logger.debug("kerberosDebug is set to : {}", kerberosDebug);
System.setProperty(SYS_PROP_KERBEROS_DEBUG, kerberosDebug); System.setProperty(SYS_PROP_KERBEROS_DEBUG, kerberosDebug);
} }
}
/** /**
* @param jcifsDomain the jcifsDomain to set * @param jcifsDomain the jcifsDomain to set
*/ */
public void setJcifsDomain(final String jcifsDomain) { public void setJcifsDomain(final String jcifsDomain) {
if (StringUtils.isNotBlank(jcifsDomain)) {
logger.debug("jcifsDomain is set to {}", jcifsDomain); logger.debug("jcifsDomain is set to {}", jcifsDomain);
Config.setProperty(JCIFS_PROP_CLIENT_DOMAIN, jcifsDomain); Config.setProperty(JCIFS_PROP_CLIENT_DOMAIN, jcifsDomain);
} }
}
/** /**
* @param jcifsDomainController the jcifsDomainController to set * @param jcifsDomainController the jcifsDomainController to set
*/ */
public void setJcifsDomainController(final String jcifsDomainController) { public void setJcifsDomainController(final String jcifsDomainController) {
if (StringUtils.isNotBlank(jcifsDomainController)) {
logger.debug("jcifsDomainController is set to {}", jcifsDomainController); logger.debug("jcifsDomainController is set to {}", jcifsDomainController);
Config.setProperty(JCIFS_PROP_DOMAIN_CONTROLLER, jcifsDomainController); Config.setProperty(JCIFS_PROP_DOMAIN_CONTROLLER, jcifsDomainController);
} }
}
/** /**
* @param jcifsPassword the jcifsPassword to set * @param jcifsPassword the jcifsPassword to set
*/ */
public void setJcifsPassword(final String jcifsPassword) { public void setJcifsPassword(final String jcifsPassword) {
if (StringUtils.isNotBlank(jcifsPassword)) {
Config.setProperty(JCIFS_PROP_CLIENT_PASSWORD, jcifsPassword); Config.setProperty(JCIFS_PROP_CLIENT_PASSWORD, jcifsPassword);
logger.debug("jcifsPassword is set to *****"); logger.debug("jcifsPassword is set to *****");
} }
}
/** /**
* @param jcifsUsername the jcifsUsername to set * @param jcifsUsername the jcifsUsername to set
*/ */
public void setJcifsUsername(final String jcifsUsername) { public void setJcifsUsername(final String jcifsUsername) {
if (StringUtils.isNotBlank(jcifsUsername)) {
logger.debug("jcifsUsername is set to {}", jcifsUsername); logger.debug("jcifsUsername is set to {}", jcifsUsername);
Config.setProperty(JCIFS_PROP_CLIENT_USERNAME, jcifsUsername); Config.setProperty(JCIFS_PROP_CLIENT_USERNAME, jcifsUsername);
} }
}
/** /**
* @param jcifsNetbiosWins the jcifsNetbiosWins to set * @param jcifsNetbiosWins the jcifsNetbiosWins to set
*/ */
public void setJcifsNetbiosWins(final String jcifsNetbiosWins) { public void setJcifsNetbiosWins(final String jcifsNetbiosWins) {
if (StringUtils.isNotBlank(jcifsNetbiosWins)) {
logger.debug("jcifsNetbiosWins is set to {}", jcifsNetbiosWins); logger.debug("jcifsNetbiosWins is set to {}", jcifsNetbiosWins);
Config.setProperty(JCIFS_PROP_NETBIOS_WINS, jcifsNetbiosWins); Config.setProperty(JCIFS_PROP_NETBIOS_WINS, jcifsNetbiosWins);
} }
}
/**
* Sets jcifs netbios cache policy.
*
* @param policy the policy
*/
public void setJcifsNetbiosCachePolicy(final String policy) {
if (StringUtils.isNotBlank(policy)) {
logger.debug("jcifsNetbiosCachePolicy is set to {}", policy);
Config.setProperty(JCIFS_PROP_NETBIOS_CACHE_POLICY, policy);
}
}
/**
* Sets jcifs socket timeout.
*
* @param timeout the timeout
*/
public void setJcifsSocketTimeout(final String timeout) {
if (StringUtils.isNotBlank(timeout)) {
logger.debug("jcifsSocketTimeout is set to {}", timeout);
Config.setProperty(JCIFS_PROP_CLIENT_SOTIMEOUT, timeout);
}
}
} }
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to Apereo under one or more contributor license
agreements. See the NOTICE file distributed with this work
for additional information regarding copyright ownership.
Apereo licenses this file to you 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 the following location:
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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="negociateSpnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoNegociateCredentialsAction"
p:mixedModeAuthentication="${cas.spnego.mixed.mode.authn:false}"
p:ntlm="${cas.spnego.ntlm:false}"
p:supportedBrowser="#{T(java.util.Arrays).asList('${cas.spnego.supportedBrowsers:MSIE,Trident,Firefox,AppleWebKit}')}"/>
<bean id="spnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoCredentialsAction"
p:send401OnAuthenticationFailure="${cas.spnego.send.401.authn.failure:false}"
p:principalFactory-ref="principalFactory"
p:centralAuthenticationService-ref="centralAuthenticationService" />
<bean id="jcifsConfig"
class="org.jasig.cas.support.spnego.authentication.handler.support.JcifsConfig"
p:jcifsServicePrincipal="HTTP/cas.example.com@EXAMPLE.COM"
p:kerberosDebug="${cas.spnego.kerb.debug:false}"
p:kerberosRealm="${cas.spnego.kerb.realm:EXAMPLE.COM}"
p:kerberosKdc="${cas.spnego.kerb.kdc:172.10.1.10}"
p:jcifsDomain="${cas.spnego.jcifs.domain:}"
p:jcifsDomainController="${cas.spnego.jcifs.domaincontroller:}"
p:jcifsNetbiosCachePolicy="${cas.spnego.jcifs.netbios.cache.policy:600}"
p:jcifsNetbiosWins="${cas.spnego.jcifs.netbios.wins:}"
p:jcifsPassword="${cas.spnego.jcifs.password:}"
p:jcifsServicePassword="${cas.spnego.jcifs.service.password:}"
p:jcifsSocketTimeout="${cas.spnego.jcifs.socket.timeout:300000}"
p:jcifsUsername="${cas.spnego.jcifs.username:}"
p:kerberosConf="${cas.spnego.kerb.conf:}"
p:useSubjectCredsOnly="${cas.spnego.use.subject.creds:false}"
p:loginConf="${cas.spnego.login.conf.file:/path/to/login.conf}" />
<bean id="spnegoAuthentication" class="jcifs.spnego.Authentication" />