2017-08-25 89 views
0

我嘗試過使用xml config的彈簧安全kerberos,然後用java config。它完全相同的配置(一個在xml中,一個在java中)。春季安全kerberos適用於xml配置,但不適用於Java配置

當我使用xml config的項目時,它可以工作。 然而,當我使用項目與Java的配置,我有這樣的堆棧跟蹤:

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful 
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:71) 
    at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) 
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) 
    at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.security.PrivilegedActionException: null 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:422) 
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:68) 
    ... 61 common frames omitted 
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96) 
    at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:856) 
    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:906) 
    at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:556) 
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) 
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) 
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:170) 
    at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:153) 
    ... 64 common frames omitted 
Caused by: sun.security.krb5.KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96 
    at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:278) 
    at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:149) 
    at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108) 
    at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:829) 
    ... 72 common frames omitted 

我不明白爲什麼它與XML配置工作,而不是用java配置。我花了很多時間去尋找,但我絕望了。 這裏我的XML配置:

<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" 
xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> 

<sec:http entry-point-ref="spnegoEntryPoint" use-expressions="true" > 
    <sec:intercept-url pattern="/" access="permitAll" /> 
    <sec:intercept-url pattern="/home" access="permitAll" /> 
    <sec:intercept-url pattern="/login" access="permitAll" /> 
    <sec:intercept-url pattern="/**" access="authenticated"/> 
    <sec:form-login login-page="/login" /> 
    <sec:custom-filter ref="spnegoAuthenticationProcessingFilter" 
     before="BASIC_AUTH_FILTER" /> 
</sec:http> 

<sec:authentication-manager alias="authenticationManager"> 
    <sec:authentication-provider ref="kerberosAuthenticationProvider" /> 
    <sec:authentication-provider ref="kerberosServiceAuthenticationProvider" /> 
</sec:authentication-manager> 

<bean id="kerberosAuthenticationProvider" 
    class="org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider"> 
    <property name="userDetailsService" ref="dummyUserDetailsService"/> 
    <property name="kerberosClient"> 
     <bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient"> 
      <property name="debug" value="true"/> 
     </bean> 
    </property> 
</bean> 

<bean id="spnegoEntryPoint" 
    class="org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint" > 
    <constructor-arg value="/login" /> 
</bean> 

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

<bean id="kerberosServiceAuthenticationProvider" 
    class="org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider"> 
    <property name="ticketValidator"> 
     <bean 
      class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator"> 
      <property name="servicePrincipal" value="${app.service-principal}" /> 
      <property name="keyTabLocation" value="${app.keytab-location}" /> 
      <property name="debug" value="true" /> 
     </bean> 
    </property> 
    <property name="userDetailsService" ref="dummyUserDetailsService" /> 
</bean> 

<bean id="dummyUserDetailsService" class="demo.DummyUserDetailsService" /> 

</beans> 

這裏我的Java的配置:

@Configuration 
@EnableWebMvcSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

@Value("${app.service-principal}") 
private String servicePrincipal; 

@Value("${app.keytab-location}") 
private String keytabLocation; 

@Bean 
public AuthenticationManager customAuthenticationManager() throws Exception { 
    return authenticationManager(); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
     .exceptionHandling() 
      .authenticationEntryPoint(spnegoEntryPoint()) 
      .and() 
     .authorizeRequests() 
      .antMatchers("/", "/home").permitAll() 
      .anyRequest().authenticated() 
      .and() 
     .formLogin() 
      .loginPage("/login").permitAll() 
      .and() 
     .logout() 
      .permitAll() 
      .and() 
     .addFilterBefore(
      spnegoAuthenticationProcessingFilter(authenticationManagerBean()), 
      BasicAuthenticationFilter.class); 
} 

@Override 
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth 
     .authenticationProvider(kerberosAuthenticationProvider()) 
     .authenticationProvider(kerberosServiceAuthenticationProvider()); 
} 

@Bean 
public KerberosAuthenticationProvider kerberosAuthenticationProvider() { 
    KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); 
    SunJaasKerberosClient client = new SunJaasKerberosClient(); 
    client.setDebug(true); 
    provider.setKerberosClient(client); 
    provider.setUserDetailsService(dummyUserDetailsService()); 
    return provider; 
} 

@Bean 
public SpnegoEntryPoint spnegoEntryPoint() { 
    return new SpnegoEntryPoint("/login"); 
} 

@Bean 
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(
     AuthenticationManager authenticationManager) { 
    SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); 
    filter.setAuthenticationManager(authenticationManager); 
    return filter; 
} 

@Bean 
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() { 
    KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); 
    provider.setTicketValidator(sunJaasKerberosTicketValidator()); 
    provider.setUserDetailsService(dummyUserDetailsService()); 
    return provider; 
} 

@Bean 
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() { 
    SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); 
    ticketValidator.setServicePrincipal(servicePrincipal); 
    ticketValidator.setKeyTabLocation(new FileSystemResource(keytabLocation)); 
    ticketValidator.setDebug(true); 
    //ticketValidator.setHoldOnToGSSContext(true); 
    return ticketValidator; 
} 

@Bean 
public DummyUserDetailsService dummyUserDetailsService() { 
    return new DummyUserDetailsService(); 
} 

} 

我指定我使用相同的密鑰表這兩個項目,編譯與相同的彈簧,引導配置相同的環境。

使用XML配置,日誌顯示

2017-08-25 12:26:37.315 DEBUG 2297 --- [nio-9000-exec-2] o.s.s.authentication.ProviderManager  : Authentication attempt using org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider 
2017-08-25 12:26:37.315 DEBUG 2297 --- [nio-9000-exec-2] .a.KerberosServiceAuthenticationProvider : Try to validate Kerberos Token 
Found KeyTab /tmp/krb5.keytab for HTTP/[email protected] 
Found KeyTab /tmp/krb5.keytab for HTTP/[email protected] 
Entered Krb5Context.acceptSecContext with state=STATE_NEW 
Java config name: file:///etc/krb5.conf 
KeyTabInputStream, readName(): EXAMPLE.COM 
KeyTabInputStream, readName(): HTTP 
KeyTabInputStream, readName(): mcottech2.example.com 
KeyTab: load() entry length: 65; type: 1 
KeyTabInputStream, readName(): EXAMPLE.COM 
KeyTabInputStream, readName(): HTTP 
KeyTab: load() entry length: 61; type: 23 
Looking for keys for: HTTP/[email protected] 
Added key: 23version: 45 
Added key: 18version: 45 
Added key: 17version: 45 
Found unsupported keytype (3) for HTTP/[email protected] 
Found unsupported keytype (1) for HTTP/[email protected] 
Added key: 17version: 44 
Added key: 23version: 44 
Added key: 18version: 44 
Added key: 17version: 44 
Found unsupported keytype (3) for HTTP/[email protected] 
Found unsupported keytype (1) for HTTP/[email protected] 
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType 
Using builtin default etypes for permitted_enctypes 
default etypes for permitted_enctypes: 18 17 16 23. 
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType 
MemoryCache: add 1503663997/005947/0A6D3E392B245A589F7F3FF28BA5991F/[email protected] to [email protected]|HTTP/[email protected] 
>>> KrbApReq: authenticate succeed. 
Krb5Context setting peerSeqNumber to: 1289436574 
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType 
Krb5Context setting mySeqNumber to: 502989002 
>>> Constrained deleg from GSSCaller{UNKNOWN} 
2017-08-25 12:26:37.364 DEBUG 2297 --- [nio-9000-exec-2] .a.KerberosServiceAuthenticationProvider : Succesfully validated [email protected] 

而與Java的配置例子中,我只得到了

2017-08-25 12:21:11.778 DEBUG 2248 --- [nio-9000-exec-4] .a.KerberosServiceAuthenticationProvider : Try to validate Kerberos Token 
Found KeyTab /tmp/file:/tmp/krb5.keytab for HTTP/[email protected] 
Found KeyTab /tmp/file:/tmp/krb5.keytab for HTTP/[email protected] 
Entered Krb5Context.acceptSecContext with state=STATE_NEW 
Java config name: file:///etc/krb5.conf 
Looking for keys for: HTTP/[email protected] 
Looking for keys for: HTTP/[email protected] 

有什麼我忘了嗎?

回答

0

使用XML配置,在application.yml,密鑰表位置必須是先於絕對路徑「文件://」

keytab-location: file:///tmp/krb5.keytab 

與Java的配置,在application.yml,密鑰表位置必須是一個需要文件協議的相對路徑。

keytab-location: krb5.keytab