Spring Kerberos 扩展、SSO 和域外机器
我一直在对 Kerberos 扩展的里程碑 2 进行 POC,以实现单点登录。
我的设置的快速摘要:
KDC: Windows Server 2003 (SP2)
Web 服务器: Ubuntu 10.04、Tomcat 5.5、Java 1.6.0_22(不在域中)
Spring: Framework 3.0.5、Security 3.0.4、Kerberos Extension 1.0.0 M2
我已将配置设置为首先尝试 SPNEGO 身份验证,如果失败则重定向到登录页面。 这是通过设置 SpnegoAuthenticationProcessingFilter 的“failureHandler”属性来完成的。我已经成功测试了这个 在域内外的 Windows 计算机(XP 和 7)上。域外的机器被重定向到 进入登录页面即可成功登录。
这是我的配置:
<?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>
当 Windows 计算机位于域之外时,我的 Web 服务器会使用 "WWW-Authenticate Negotiate" 标头(如往常一样)进行响应 Windows 计算机使用 NTLM 标头(“协商 TlRM...”)进行响应,其中 SpnegoAuthenticationProcessingFilter 然后显示“协商标头无效...” 并将用户重定向到登录页面。伟大的。
问题:
有许多永久位于域之外的 Mac 和 Linux 计算机需要使用此 Web 应用程序。 当他们点击网络应用程序(使用 Firefox 3.6)时,我的网络服务器会使用预期的 “WWW-Authenticate Negotiate” 标头进行响应以通知 客户端认为 Web 应用程序已进行 Kerberized,但 Mac 或 Linux 计算机根本没有响应。因此 SpnegoAuthenticationProcessingFilter 不会再次输入,因此不会失败,并且随后不会重定向到登录页面。
问题:
为什么 Mac 和 Linux 机器的响应方式与 Windows 机器不同(不敢相信我刚刚问了这个……)?
我知道当 Mac 和 Linux 机器获得票证(通过 kinit)时,它们能够进行身份验证,但这似乎不是一个好的解决方案 根本没有,因为它需要用户努力提供凭证等,而票据也会过期。
那么有什么方法可以让这些机器像 Windows 机器一样发回 NTLM 标头呢? 或者如果有任何其他建议/方法请告诉我。
顺便说一句,我确实配置了用于在 Mac 和 Linux 计算机上测试的 Firefox("network.negotiate-auth.delegation-uris" 和 "network.negotiate-auth.trusted- uris” 设置为“.corpza.corp.co.za”)。
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 M2
I 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 the 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").
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您似乎没有设置 network.automatic-ntlm-auth.trusted-uris。你读过这篇文章吗?
https://developer.mozilla.org/en/Integrated_Authentication
授予
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
你走错路了。不要依赖失败的 SPNEGO 过滤器。 Linux 和 Mac 客户端的行为与 Windows 客户端一样正确。一般设置应如下所示,如果过滤器未实现/支持该设置,则您发现了一个错误。
现在,您依靠从 Windows 客户端发送的错误/不可处理的数据来呈现表单。您应该直接发送带有 401 的表单,以便所有客户端都能够选择适当的登录方法(SPNEGO 或表单,即故障通过)。请记住,表单身份验证不是像 Negotiate、Digest 或 Basic 这样的 http 身份验证。必须以不同的方式对待它。
我们也在使用该过滤器,但我对此不太满意。所以我有实践经验。
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.
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.