web-dev-qa-db-ja.com

Kerberos / Spring Security / IE / Active Directoryでの「欠陥のあるトークンが検出されました」エラー(KerberosではなくNTLM)

Spring Security/Kerberos/ADをWebアプリで機能させるのに問題があります。私たちの診断は、ADサーバーがNTLMトークン( "TlRMTVNT ....."で始まるのでわかります)をIEに送信していて、IEがこれをアプリケーションに送信していて、失敗しているということです。 。 ADサーバーはKerberos/SPNEGOトークンをIEに送信する必要があります。

「可動部分」は次のとおりです。

  • Spring Security 3.0(パッチ適用済み)
  • Microsoft Windows Server Enterprise 2003 SP1 Active Directory
  • IE 8
  • Tomcat(TCサーバー6.0)
  • Java 1.6

以下の手順で詳細に説明されているように、すべてをセットアップしました。

https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension

これには以下が含まれます:

  • 通常のユーザーをサービスプリンシパルとして作成する(アプリケーションが存在するマシン名と同じ)。次のアカウントオプションを設定します。
    • 「次のログオン時にパスワードを変更する必要があります」を無効化
    • 有効化された「パスワードは無期限」
    • 「Kerberos DESを使用…」を有効化
    • 「Kerberos事前認証を要求しない」を無効化
    • 注:Server 2003では、「このアカウントはKerberos AES 128ビットをサポートしています...」および「このアカウントはKerberos AES 256ビットをサポートしています...」オプションは表示されません
  • 「ktpass.exe」を使用して、この新しいユーザーにサービスプリンシパル名(SPN)を割り当て、このユーザーキーをキータブファイルにエクスポートしました。 'ktpass/out ourweb.keytab/mapuser [email protected]/princ HTTP/[email protected]/passを使用* '
  • https://src.springframework.org/svn/se-security/trunk からダウンロードしたソースコード。
  • ADサーバーからソースコード(アプリケーション)のWEB-INF/etcにkeytabファイルをコピーしました。
  • Keytabファイルを読み取るために、ファイルSunJaasKerbersoTicketValidator.Javaを変更しました。 (アプリケーションがJavaクラスパスからkeytabファイルを読み取れないというバグを解決するため)options.put( "keyTab"、 "C:\ se-security\spring-security-kerberos\spring-security -kerberos-sample\src\main\webapp\WEB-INF\etc\ourweb.keytab ");
  • Spnego.xmlを使用するようにweb.xmlを構成しました。 contextConfigLocation /WEB-INF/spnego.xml
    • サービスプリンシパル名とキータブファイルの場所を指定して、Kerberos(SpnegoEntryPoint、SpnegoAuthenticationProcessingFilter、およびKerberosServiceAuthenticationProvider Bean)を使用するようにSpring Security(spnego.xml)を構成しました。
    • WEB-INF/etcにコピーされたkeytabファイルを読み取るようにspnego.xmlを構成しました。

TCサーバーを起動すると、問題なく初期化されていることが確認できます(つまり、エラーなし-「キータブから取得されたプリンシパルキー」)。

Creating instance of bean 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8' 
Invoking afterPropertiesSet() on bean with name 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8' 
Config name: C:\WINDOWS\krb5.ini
Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is C:\se-security\spring-security-kerberos\spring-security-kerberos-sample\src\main\webapp\WEB-INF\etc\ourwebapp4.keytab refreshKrb5Config is false principal is HTTP/ourwebappweb4.testdomain.ourcompany.co.uk tryFirstPass is false useFirstPass is false storePass is false clearPass is false
>>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): ourweb
>>> KeyTab: load() entry length: 78; type: 1
>>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): ourweb.testdomain.ourcompany.co.uk
>>> KeyTab: load() entry length: 113; type: 1
Added key: 1version: 2
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 1.
0: EncryptionKey: keyType=1 kvno=2 keyValue (hex dump)=
0000: 91 01 43 E3 02 A8 B9 83   

principal's key obtained from the keytab
principal is HTTP/[email protected]
EncryptionKey: keyType=1 keyBytes (hex dump)=0000: 91 01 43 E3 02 A8 B9 83   
Added server's keyKerberos Principal HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UKKey Version 2key EncryptionKey: keyType=1 keyBytes (hex dump)=
0000: 91 01 43 E3 02 A8 B9 83   

[Krb5LoginModule] added Krb5Principal  HTTP/[email protected] to Subject Commit Succeeded 

Finished creating instance of bean 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8' 

テストの準備ができたら、IEで「Windows統合認証」を有効にし、ドメインがIEのローカルイントラネットサイトセクションにリストされていることを確認しました。次に、完全修飾ドメイン名を使用してWebアプリケーションに接続しました。

その際、ブラウザに次のエラーが表示されました。

500 Internal server error.

tCサーバーのログファイル:

Negotiate Header was invalid: Negotiate     TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw== 
  org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesfull
  at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.Java:74)
  at org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.Java:92)
  at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.Java:120)
  at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.Java:48)
  at org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.Java:132)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:355)
  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:79)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:355)
  at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:149)
  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
  at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
  at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:235)
  at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
  at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:233)
  at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:191)
  at com.springsource.metrics.collection.web.HttpRequestMetricCollectionValve.invoke(HttpRequestMetricCollectionValve.Java:44)
  at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:128)
  at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:102)
  at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:109)
  at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:293)
  at org.Apache.coyote.http11.Http11Processor.process(Http11Processor.Java:849)
  at org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.Java:583)
  at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:379)
  at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:886)
  at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:908)
  at Java.lang.Thread.run(Thread.Java:619)
Caused by: Java.security.PrivilegedActionException: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
  at Java.security.AccessController.doPrivileged(Native Method)
  at javax.security.auth.Subject.doAs(Subject.Java:396)
  at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.Java:72)
  ... 25 more
Caused by: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
  at Sun.security.jgss.GSSHeader.<init>(GSSHeader.Java:80)
  at Sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.Java:287)
  at Sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.Java:267)
  at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.Java:161)
  at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.Java:1)
  ... 28 more
SecurityContextHolder now cleared, as request processing completed

ADLMサーバーがIEにNTLMトークン( "TlRMTVNT ....."で始まるのでわかる)を送信し、次にIEがこれを私たちのアプリケーションに渡すと失敗します。

ADサーバーはKerberos/SPNEGOトークンをIEに送信する必要があります。

その他の注意事項:

  • サーバー(tcサーバー)とクライアント(ブラウザー)は、異なる(仮想)マシンと同じドメインにあります
30

これは、クライアントとサーバーを同じマシンで実行しているときに発生する可能性があります。 IEを使用してTomcatを実行しているマシンと通信する場合、これらが異なるマシンであることを確認してください。

さらに、サーバーマシンがキータブで指定されたドメイン(testdomain.ourcompany.co.uk)に参加していることを確認する必要があります。そうしないと、NTLMに戻る可能性があります。サーバーがドメインに参加していないマシン上にある場合でもキータブは機能しますが(表示したニースキータブ復号化が表示されます)、IEは混乱してしまい、正しいこと。

ADは本当にServer 2003のarcfour-hmacを話すのが好きなので、krb5.iniファイルでこれを正しく設定することを確認する必要があります。

次のようにキータブを正しく作成できます。

C:\>ktpass -princ HTTP/[email protected] -mapuser [email protected] -crypto RC4-HMAC-NT -ptype K
RB5_NT_PRINCIPAL -pass * -out ourweb.keytab
Targeting domain controller: test-dc.ourcompany.co.uk
Using legacy password setting method
Successfully mapped HTTP/[email protected] to ourweb.testdomain.ourcompany.co.uk.
Key created.
Output keytab to ourweb.keytab:
Keytab version: 0x502
keysize 75 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL)
vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0fd0e500225c4fca9a63a9998b17ca32)

あなたがkrb5.iniファイルを設定したことは知りませんでした。サーバーマシン(デフォルトの場所はC:\ WINDOWS\krb5.ini)で正しく設定する必要があります。

[domain_realm]  
    .testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK
    testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK

[libdefaults]   
    default_realm = TESTDOMAIN.OURCOMPANY.CO.UK
    permitted_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 
    default_tgs_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 
    default_tkt_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 

[realms]    
VERDAD.LOCAL = {        
    kdc = test-dc.ourcompany.co.uk  
    admin_server = test-dc.ourcompany.co.uk
    default_domain = TESTDOMAIN.OURCOMPANY.CO.UK
}

次のプロパティを設定する必要がある場合もあります(これをIDEから実行しようとしている場合)。

<systemProperties>
  <Java.security.krb5.kdc>test-dc.ourcompany.co.uk</Java.security.krb5.kdc>
  <Java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</Java.security.krb5.realm>
</systemProperties>

私はこれらをpomファイルで次のように設定するmaven用のorg.codehaus.mojoプラグインを使用していました:

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>Tomcat-maven-plugin</artifactId>
      <configuration>
        <server>Tomcat-development-server</server>
        <port>8080</port>
        <path>/SecurityTest</path>
        <systemProperties>
          <Java.security.krb5.kdc>test-dc.ourcompany.co.uk</Java.security.krb5.kdc
          <Java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</Java.security.krb5.realm>
        </systemProperties>
      </configuration>
    </plugin>
  </plugins>
</build>
29
Grant Cermak

私もこの問題に遭遇しました。将来この問題が発生する不運な人にとって、この問題の別の原因は、Aレコード(ホスト名)ではなく、IPでサーバーにアクセスすることです。

7
Lior Chaga

私も同じ問題を抱えていて、犯人を見つけるのに非常に長い時間がかかりました。したがって、上記のすべてを実行しても、KerberosではなくNTLMトークンが使用される場合。重複するSPNがないことを確認してください。私の場合、同じSPNにマップされた2つのアカウントがあり、その理由は以前に別のサービスアカウントを使用して同じサーバー上で別のWebアプリを実行したが、HTTP /

それが役に立てば幸い

5
arash