BadCredentialsException:Kerberos 验证不成功

Posted

技术标签:

【中文标题】BadCredentialsException:Kerberos 验证不成功【英文标题】:BadCredentialsException: Kerberos validation not succesfull 【发布时间】:2012-09-13 02:03:11 【问题描述】:

我想使用 SPNEGO 执行身份验证。我用:

spring-core-3.1.0.RELEASE.jar spring-security-core-3.1.0.RELEASE.jar spring-security-kerberos-core-1.0.0.M2.jar spring 包编解码器 核心安全 3.0.7 (https://jira.springsource.org/browse/SES-98) tomcat

我的配置文件如下所示。当我尝试使用上述库进行身份验证时,出现以下异常。

有人遇到同样的问题并处理了吗?

配置文件(取自 spring security kerberos 示例):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <!-- This configuration uses SPNEGO by default, but one could also use a form if he directly goes to /login.html -->
    <sec:http entry-point-ref="spnegoEntryPoint" use-expressions="true">
        <sec:intercept-url pattern="/secure/**" access="isAuthenticated()" />
        <sec:custom-filter ref="spnegoAuthenticationProcessingFilter"
            position="BASIC_AUTH_FILTER" />
        <sec:form-login login-page="/login.html" default-target-url="/secure/index.jsp"/>
    </sec:http>

    <bean id="spnegoEntryPoint"
        class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />

    <bean id="spnegoAuthenticationProcessingFilter"
        class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider ref="kerberosServiceAuthenticationProvider" /> <!-- Used with SPNEGO -->
        <sec:authentication-provider user-service-ref="dummyUserDetailsService"/> <!-- Used with form login -->
    </sec:authentication-manager>



    <bean id="kerberosServiceAuthenticationProvider"
        class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
        <property name="ticketValidator">
            <bean
                class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
                <property name="servicePrincipal" value="HTTP/xxx.xx.xx.xx@XX-XXX.XXX.XX" />
                <!-- Setting keyTabLocation to a classpath resource will most likely not work in a Java EE application Server -->
                <!-- See the Javadoc for more information on that -->
                <property name="keyTabLocation" value="file:/home/xxxxx/conf/krb5/krb5.keytab" />
                <property name="debug" value="true" />
            </bean>
        </property>
        <property name="userDetailsService" ref="dummyUserDetailsService" />
    </bean>

    <!-- This bean definition enables a very detailed Kerberos logging -->
    <bean
        class="org.springframework.security.extensions.kerberos.GlobalSunJaasKerberosConfig">
        <property name="debug" value="true" />
    </bean>

    <!--
        Just returns the User authenticated by Kerberos and gives him the
        ROLE_USER
    -->

    <bean id="dummyUserDetailsService"
        class="org.springframework.security.extensions.kerberos.sample.DummyUserDetailsService" />

</beans>

我得到的异常:

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesfull
        at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:69)
        at org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:86)
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
        at org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:131)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.ha.session.JvmRouteBinderValve.invoke(JvmRouteBinderValve.java:219)
        at org.apache.catalina.ha.tcp.ReplicationValve.invoke(ReplicationValve.java:333)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
Caused by: java.security.PrivilegedActionException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate
type to decrypt AP REP - RC4 with HMAC)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:415)
        at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:67)
        ... 29 more
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC)
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:778)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
        at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:871)
        at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:544)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
        at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:146)
        at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136)
        ... 32 more
Caused by: KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC
        at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:273)
        at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:144)
        at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108)
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:761)
        ... 40 more

【问题讨论】:

嗯,对我来说似乎是个错误。尝试在Spring Security's JIRA 填写票证。 这看起来像是 kerberos 配置问题。检查您的密钥表文件是否包含正确类型的密钥(rc4-hmac 为 23)。 【参考方案1】:

我发现了问题。 Spring-security-kerbos 需要 keytab 文件的路径作为“资源字符串”(详细信息:http://static.springsource.org/spring/docs/3.0.x/reference/resources.html)。 当我将路径设置为“file:/home/xxxxx/conf/krb5/krb5.keytab”时,应用程序会运行,但我认为它稍后无法打开文件并且 Kerberos 无法加载任何密钥。不幸的是,来自 Kerberos 的日志不是很清楚。

当我将路径设置为“/home/xxxxx/conf/krb5/krb5.keytab”时,出现以下异常

Caused by: java.io.FileNotFoundException: ServletContext resource [/home/xxxxx/conf/krb5/krb5.keytab] cannot be resolved to URL because it does not exist

此问题的解决方案可以是文件 SunJaasKerberosTicketValidator.java 中的修复:

private String keyTabLocation;

LoginConfig loginConfig = new LoginConfig(keyTabLocation, servicePrincipal, debug);

代替:

private Resource keyTabLocation;

LoginConfig loginConfig = new LoginConfig(keyTabLocation.getURL().toExternalForm(), servicePrincipal, debug);

有了这个修复,一切正常。我们可以设置“/home/xxxxx/conf/krb5/krb5.keytab”格式的文件路径

如果有人知道更多细节,请写在这里。

【讨论】:

如何创建 LoginConfig 类的实例,因为它是 SunJaasKerberosTicketValidator 的私有内部类?我也面临类似的问题('校验和失败')并在此链接(***.com/questions/57726513/…)上发布了我的查询,请检查并找到任何建议吗? 仅将 SunJaasKerberosTicketValidator 复制到您的项目并更改代码【参考方案2】:

至少 Java 7 不(或者,我的版本不)能够处理“文件:”前缀:See this link。我必须像您一样对 Spring 源代码进行相同的修改。谢谢,这很有帮助。浪费了半周时间尝试不同的配置。

【讨论】:

这似乎不是问题的答案。您应该将其发布为对另一个答案的评论。

以上是关于BadCredentialsException:Kerberos 验证不成功的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Security:AuthenticationManager 抛出 BadCredentialsException 时返回状态 401

如何从自定义身份验证提供程序类更改 Json 格式的 BadCredentialsException、UserNameNotFound 异常消息

覆盖 spring-security BadCredentialsException 的容器响应

SpringSecurity(二十):异常处理

Spring Security教程外篇---- AuthenticationException异常详解

Spring Boot 1.4:Principal 不能为 null 异常