I have been POC'ing with milestone 2 of the Kerberos extension to achieve single sign-on.
Quick summary of my setup:
KDC: Windows Server 2003 (SP2) Web server: Ubuntu 10.04, Tomcat 5.5, Java 1.6.0_22 (not on the domain) Spring: Framework 3.0.5, Security 3.0.4, Kerberos Extension 1.0.0 M2I have setup my configuration to first attempt SPNEGO authentication and if it fails to then redirect to a login page. This is done by setting SpnegoAuthenticationProcessingFilter's "failureHandler" property. I have successfully tested this on Windows machines (XP and 7) that are in and out of the domain. The machines that are outside the domain gets redirected to the login page and then can successfully login.
Here is my config:<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http entry-point-ref="spnegoEntryPoint" auto-config="false">
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/j_spring_security_check*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<form-login login-page="/login.html" default-target-url="/" always-use-default-target="true"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="kerberosServiceAuthenticationProvider" />
<authentication-provider ref="kerberosAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="spnegoEntryPoint"
class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />
<beans:bean id="spnegoAuthenticationProcessingFilter"
class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
<beans:property name="failureHandler">
<beans:bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.html" />
<beans:property name="allowSessionCreation" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="kerberosServiceAuthenticationProvider"
class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
<beans:property name="ticketValidator">
<beans:bean
class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
<beans:property name="servicePrincipal" value="HTTP/mywebserver.corpza.corp.co.za"/>
<beans:property name="keyTabLocation" value="classpath:mywebserver.keytab" />
<beans:property name="debug" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService" />
</beans:bean>
<beans:bean id="kerberosAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosAuthenticationProvider">
<beans:property name="kerberosClient">
<beans:bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosClient">
<beans:property name="debug" value="true" />
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService" />
</beans:bean>
<beans:bean class="org.springframework.security.extensions.kerberos.GlobalSunJaasKerberosConfig">
<beans:property name="debug" value="true" />
<beans:property name="krbConfLocation" value="/etc/krb5.conf" />
</beans:bean>
<beans:bean id="dummyUserDetailsService" class="main.server.DummyUserDetailsService"/>
</beans:beans>
When the Windows machine is outside the domain my web server responds with the "WWW-Authenticate Negotiate" header (as per usual) to which the Windows machine responds to with a NTLM header ("Negotiate TlRM..."), where the SpnegoAuthenticationProcessingFilter then says "Negotiate Header was invalid..." and awesomly redirects the user to the login page. Great.
The Issue:
There are a number of Mac and Linux machines that are permanently outside the domain which would need to use this web app. When they hit the web app (with Firefox 3.6) my web server responds with the expected "WWW-Authenticate Negotiate" header to inform the client that the web app is Kerberized, BUT neither the Mac or Linux machines responds at all. Thus the SpnegoAuthenticationProcessingFilter doesn't get entered again and hence no failure and subsequently no redirection to the login page takes place.The Question:
Why doesn't the Mac and Linux machines respond in the same way as the Windows machines (can't belive I just asked that...)?I know that when th开发者_如何学Goe Mac and Linux machines obtain a ticket (via kinit) they are able to authenticated but this doesn't seem like a good solution at all as it requires effort from the user to provide credentials etc. where the tickets expires as well.
So is there any way that we can get these machines to send back a NTLM header as the Windows machines does? Or if there are any other suggestions/ways please let me know.
B.t.w. I did configure the Firefoxes that I used on to test on the Mac and Linux machines ("network.negotiate-auth.delegation-uris" and "network.negotiate-auth.trusted-uris" was set to ".corpza.corp.co.za").
It doesn't look like you set network.automatic-ntlm-auth.trusted-uris. Did you read through this?
https://developer.mozilla.org/en/Integrated_Authentication
Grant
You are going the wrong way. Don't rely on the failing SPNEGO filter. The Linux and Mac clients behave correctly just as the Windows client does. The general setup should look like the following, if the filter does not implement/support that, you have found a bug.
- Client sends a request to the server
- Client receives "401 WWW-Authenticate: Negotiate" from the server (or any combination of Negotiate, Basic, Digest).
- Client tries to supply auth data and if it fails it shows the 401 page.
Now you rely on faulty/non-processible data sent from the Windows client to present the form. You should rather send the form with the 401 directly to give all clients the ability to choose an appropriate login method (SPNEGO or form, ie. fail-through). Keep in mind that form auth is not an http auth like Negotiate, Digest or Basic. It has to be treated differently.
We are using that filter too and I am not really happy with it. So I have hands-on experience.
精彩评论