Kerberos:协商标头无效(原因GSSException:没有提供有效的凭据(机制级别:无法找到任何Kerberos credentails))

时间:2019-05-15 09:20:48

标签: java spring spring-security single-sign-on spring-security-kerberos

痛苦!

由于来自Kerberos代码深处的异常,我尝试通过SSO使用Spring Security 5和Kerberos验证用户的尝试失败。我将首先显示堆栈跟踪和引起它的代码,然后提供有关我的环境的其他信息,这可能有助于消除某些可能性。

堆栈跟踪

ConstraintLayout
  1. 因此,当我的WARN 3932 --- [apr-8080-exec-1] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIILSwYGKwYBBQUCoIILPzCCCzugMDAuBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCN[and so on] org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:71) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE] at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-5.1.1.RELEASE.jar:5.1.1.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:512) ~[spring-security-config-5.1.1.RELEASE.jar:5.1.1.RELEASE] ... Caused by: java.security.PrivilegedActionException: null at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_162] at javax.security.auth.Subject.doAs(Subject.java:422) ~[na:1.8.0_162] at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:68) ~[spring-security-kerberos-core-1.0.1.RELEASE.jar:1.0.1.RELEASE] ... Caused by: org.ietf.jgss.GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails) at sun.security.jgss.krb5.Krb5AcceptCredential.getInstance(Krb5AcceptCredential.java:87) ~[na:1.8.0_162] at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:127) ~[na:1.8.0_162] at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:198) ~[na:1.8.0_162] 正在验证SSO票证时,有一个BadCredentialsException。这只是抛出来自

    SunJaasKerberosTicketValidator
    PrivilegedActionException

    }

  2. public KerberosTicketValidation validateTicket(byte[] token) { try { return Subject.doAs(this.serviceSubject, new KerberosValidateAction(token)); } catch (PrivilegedActionException e) { throw new BadCredentialsException("Kerberos validation not successful", e); } 来自PrivilegedActionException方法native,因此很难跟踪。我不知道执行情况。 我觉得很有趣java.security.AccessController.doPrivileged打印为

    PrivilegedActionException

    Caused by: java.security.PrivilegedActionException: null 方法是

    PrivilegedActionException.toString

    因此,public String toString() { String s = getClass().getName(); return (exception != null) ? (s + ": " + exception.toString()) : s; } (原因异常)不为null,但是它以exception ...

  3. 的形式输出
  4. 但是,堆栈跟踪告诉我们问题的根源是来自Krb5AcceptCredential类的null

    GSSException

    if (creds == null) throw new GSSException(GSSException.NO_CRED, -1,"Failed to find any Kerberos credentails"); 是因为creds == null(请参阅implementation)返回Krb5Util.getServiceCreds而没有引起异常。

这是我到目前为止所走的路。现在,一些其他信息。

在我的WebSecurityConfig中创建票证验证器

null

创建KerberosServiceAuthenticationProvider

这是将抛出 SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); ticketValidator.setServicePrincipal("HTTP/host@REALM"); FileSystemResource fs = new FileSystemResource("PATH_TO_KEYTAB"); ticketValidator.setKeyTabLocation(fs); LOGGER.info(fs.exists()); // prints 'true' 的对象的配置。

BadCredentialsException

我知道SSO可以工作

我有能力证明我公司的SSO基础架构正常运行。同一台服务器正在运行另一个应用程序(带有Kerberos的Spring Security 4),可以通过SSO成功验证用户身份。因此,我的设置很可能有问题。

顺便说一下,我使用的是Chrome,但我也通过IE对其进行了测试。

如果您需要我的 KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); provider.setTicketValidator(sunJaasKerberosTicketValidator()); provider.setUserDetailsService(myUserDetailService); provider.supports(KerberosServiceRequestToken.class); 或其他信息,我会提供。愿力量与您同在:-)

其他问题

这是我到目前为止发现的,但是这些示例略有不同。

1 个答案:

答案 0 :(得分:1)

我遇到这个问题已经 2 年了,但我记得,我解决了它......但忘记在这里发布解决方案(我的错)。由于这个问题得到了一些新的关注,我会尽力记住。

我挖出了代码,我想我记住了这个问题。在 WebSecurityConfig 中有一些方法注释为 @Bean - 并且缺少一个。 我认为是 SunJaasKerberosTicketValidator。它在此类中用于配置 KerberosServiceAuthenticationProvider,但 Spring Security 似乎也在内部使用该 Bean - 如果 Spring 上下文中缺少该 Bean,则会失败。

这是我当时代码的(缩短的)版本。如果您也有 @Bean 注释的所有方法,请检查它们。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
        auth.authenticationProvider(kerberosServiceAuthenticationProvider());  
    }

    @Override
    public void configure(WebSecurity web) {
        // ...
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //...
    }

    @Bean
    public SpnegoEntryPoint spnegoEntryPoint() {
        //...
    }

    private KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
        KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
        provider.setTicketValidator(ticketValidator());
        provider.setUserDetailsService(myUserDetailsService);
        return provider;
    }

    @Bean
    public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter() {
        SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
        AuthenticationFailureHandler failureHandler =
            new SimpleUrlAuthenticationFailureHandler(AUTHENTIFICATION_FAILED_URL);
        filter.setFailureHandler(failureHandler);
        try {
            filter.setAuthenticationManager(authenticationManagerBean());
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        return filter;
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public SunJaasKerberosTicketValidator ticketValidator() {
        SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
        ticketValidator.setDebug(true);
        ticketValidator.setServicePrincipal(kerberosConfigMgmt.securityKerberosServicePrincipal());

        FileSystemResource fs = new FileSystemResource(kerberosConfigMgmt.securityKerberosKeyTapFileAbsolutePath());
        ticketValidator.setKeyTabLocation(fs);

        return ticketValidator;
    }

    @Bean(name = "authenticationSuccessHandler")
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return new SimpleUrlAuthenticationSuccessHandler(STARTSEITE_URL);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}