Как исправить исключение "Невозможно войти в систему как субъекта службы", вызванное "Невозможно получить пароль от пользователя" для проверки подлинности Tomcat Windows?

Я пытаюсь реализовать проверку подлинности Windows для веб-приложений Tomcat8.0, используя встроенную поддержку. И я получаю следующее исключение в файле TOMCAT_HOME\logs\tomcat8-stderr.2017-03-17.log:-

17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.authenticator.AuthenticatorBase.invoke Security checking request GET /testad/
17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Common Area]' against GET /index.jsp --> true
17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.realm.RealmBase.findSecurityConstraints   Checking constraint 'SecurityConstraint[Common Area]' against GET /index.jsp --> true
17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.authenticator.AuthenticatorBase.invoke  Calling hasUserDataPermission()
17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.realm.RealmBase.hasUserDataPermission   User data constraint has no restrictions
17-Mar-2017 10:59:39.367 FINE [http-nio-8080-exec-6] org.apache.catalina.authenticator.AuthenticatorBase.invoke  Calling authenticate()
17-Mar-2017 10:59:39.383 SEVERE [http-nio-8080-exec-6] org.apache.catalina.authenticator.SpnegoAuthenticator.doAuthenticate Unable to login as the service principal
 javax.security.auth.login.LoginException: Unable to obtain password from user

    at com.sun.security.auth.module.Krb5LoginModule.promptForPass(Unknown Source)
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
    at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.access$000(Unknown Source)
    at javax.security.auth.login.LoginContext$4.run(Unknown Source)
    at javax.security.auth.login.LoginContext$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
    at javax.security.auth.login.LoginContext.login(Unknown Source)
    at org.apache.catalina.authenticator.SpnegoAuthenticator.doAuthenticate(SpnegoAuthenticator.java:197)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:556)
    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(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

17-Mar-2017 10:59:39.383 FINE [http-nio-8080-exec-6] org.apache.catalina.authenticator.AuthenticatorBase.invoke  Failed authenticate() test

Ниже приведены подробности моей среды:-

  1. Windows Server 2012 (полное доменное имя: dev.devdevelopment.com) для AD
  2. Windows 7 (полное доменное имя: windows7devpc.devdevelopment.com) для Apache Tomcat 8.5.11 с Java 1.8.0_31(64-разрядная версия)
  3. Windows XP машина как клиент (браузер Firefox)
  4. Доменное имя AD: devdevelopment.com

У меня есть пользователь домена devtomcat, которому сопоставлены следующие имена участников-служб:

У меня есть другой пользователь домена devuser, который является членом группы с именем tc-webapp-users, которая входит в подразделение с именем tomcat-ou. Этот пользователь используется для доступа к веб-приложению с компьютера Windows XP.

Следующее - server.xml моего кота

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources/>

  <Service name="Catalina">
    <Connector port="8080" maxSavePostSize="2097152" URIEncoding="UTF-8" maxHttpHeaderSize="65536"/>
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
        <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
            <Context docBase="testad" path="/testad">
                <Realm className="org.apache.catalina.realm.JNDIRealm"
                        connectionURL="ldap://dev.devdevelopment.com:389"
                        userSubtree="true"
                        userBase="CN=Users,DC=devdevelopment,DC=com"
                        userSearch="(sAMAccountName={0})"
                        userRoleName="memberOf"
                        roleBase="CN=tc-webapp-users,OU=tomcat-ou,DC=devdevelopment,DC=com"
                        roleName="cn"
                        roleSearch="(member={0})"
                        roleSubtree="true"
                        roleNested="true"/>
                <Valve className="org.apache.catalina.authenticator.SpnegoAuthenticator" storeDelegatedCredential="true"/>
            </Context>
        </Host>
    </Engine>
  </Service>
</Server>

Ниже приводится веб-приложение web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Common Area</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
            <http-method>PUT</http-method>
            <http-method>HEAD</http-method>
            <http-method>TRACE</http-method>
            <http-method>DELETE</http-method>
            <http-method>OPTIONS</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>tc-webapp-users</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>SPNEGO</auth-method>
    </login-config>

    <security-role>
        <description>TC-WebApp-Roles</description>
        <role-name>tc-webapp-users</role-name>
    </security-role>
</web-app>

Ниже приводится содержимое файла krb5.ini, который находится в каталоге C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf:-

[libdefaults]
default_realm=DEVDEVELOPMENT.COM
default_keytab_name=“C:/Program Files/Apache Software Foundation/Tomcat 8.5/conf/tomcat.keytab"
default_tkt_enctypes=rc4-hmac,aes256-cts-hmac-shal-96,aes128-cts-hmac-shal-96
default_tgs_enctypes=rc4-hmac,aes256-cts-hmac-shal-96,aes128-cts-hmac-shal-96
permitted_enctypes=rc4-hmac,aes256-cts-hmac-shal-96,aes128-cts-hmac-shal-96
udp_preference_limit=1
forwardable=true

[realms]
DEVDEVELOPMENT.COM={
    kdc=dev.devdevelopment.com
}

[domain_realm]
devdevelopment.com=DEVDEVELOPMENT.COM
.devdevelopment.com=DEVDEVELOPMENT.COM

Ниже приведено содержимое файла jaas.conf, который находится в каталоге C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf:-

com.sun.security.jgss.krb5.accept {
    com.sun.security.auth.module.Krb5LoginModule required
    doNotPrompt=true
    principal="HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM"
    keyTab="C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab"
    storeKey=true
    useKeyTab=true
    useTicketCache=true
    isInitiator=true
    refreshKrb5Config=true
    moduleBanner=true
    storePass=true;
};

com.sun.security.jgss.krb5.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    doNotPrompt=true
    principal="HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM"
    keyTab="C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab"
    storeKey=true
    useKeyTab=true
    useTicketCache=true
    isInitiator=true
    refreshKrb5Config=true
    moduleBanner=true
    storePass=true
    debug=true;
};

Ниже приведен диагностический вывод команды JDK klist (запущенной на компьютере Tomcat):-

c:\Program Files\Java\jdk1.8.0_31\bin>klist -e -k -t "C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab"

Key tab: C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab, 1 entry found.

[1] Service principal: HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
         KVNO: 12
         Key type: 18
         Time stamp: Jan 01, 1970 05:30:00

Ниже приведен диагностический вывод команды JDK kinit (запущенной на компьютере Tomcat) в режиме отладки:-

c:\Program Files\Java\jdk1.8.0_31\bin>kinit -J-Dsun.security.krb5.debug=true -k -t "C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab" HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
>>>KinitOptions cache name is C:\Users\devtomcat\krb5cc_devtomcat
Principal is HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
>>> Kinit using keytab
>>> Kinit keytab file name: C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\tomcat.keytab
Java config name: null
LSA: Found Ticket
LSA: Made NewWeakGlobalRef
LSA: Found PrincipalName
LSA: Made NewWeakGlobalRef
LSA: Found DerValue
LSA: Made NewWeakGlobalRef
LSA: Found EncryptionKey
LSA: Made NewWeakGlobalRef
LSA: Found TicketFlags
LSA: Made NewWeakGlobalRef
LSA: Found KerberosTime
LSA: Made NewWeakGlobalRef
LSA: Found String
LSA: Made NewWeakGlobalRef
LSA: Found DerValue constructor
LSA: Found Ticket constructor
LSA: Found PrincipalName constructor
LSA: Found EncryptionKey constructor
LSA: Found TicketFlags constructor
LSA: Found KerberosTime constructor
LSA: Finished OnLoad processing
Native config name: C:\Windows\krb5.ini
>>> Kinit realm name is DEVDEVELOPMENT.COM
>>> Creating KrbAsReq
>>> KrbKdcReq local addresses for windows7devpc are:

        windows7devpc/192.168.1.229
IPv4 address

        windows7devpc/fe80:0:0:0:80f2:1a68:c0f0:710%11
IPv6 address
>>> KdcAccessibility: reset
>>> KeyTabInputStream, readName(): DEVDEVELOPMENT.COM
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): windows7devpc.devdevelopment.com
>>> KeyTab: load() entry length: 107; type: 18
Looking for keys for: HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
Added key: 18version: 12
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=dev.devdevelopment.com. UDP:88, timeout=30000, number of retries =3, #bytes=227
>>> KDCCommunication: kdc=dev.devdevelopment.com. UDP:88, timeout=30000,Attempt =1, #bytes=227
>>> KrbKdcReq send: #bytes read=227
>>>Pre-Authentication Data:
         PA-DATA type = 19
         PA-ETYPE-INFO2 etype = 18, salt = DEVDEVELOPMENT.COMHTTPwindows7devpc.devdevelopment.com, s2kparams = null

>>>Pre-Authentication Data:
         PA-DATA type = 2
         PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
         PA-DATA type = 16

>>>Pre-Authentication Data:
         PA-DATA type = 15

>>> KdcAccessibility: remove dev.devdevelopment.com.:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
         sTime is Thu Mar 16 22:50:19 IST 2017 1489684819000
         suSec is 759798
         error code is 25
         error Message is Additional pre-authentication required
         sname is krbtgt/DEVDEVELOPMENT.COM@DEVDEVELOPMENT.COM
         eData provided.
         msgType is 30
>>>Pre-Authentication Data:
         PA-DATA type = 19
         PA-ETYPE-INFO2 etype = 18, salt = DEVDEVELOPMENT.COMHTTPwindows7devpc.devdevelopment.com, s2kparams = null

>>>Pre-Authentication Data:
         PA-DATA type = 2
         PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
         PA-DATA type = 16

>>>Pre-Authentication Data:
         PA-DATA type = 15

KrbAsReqBuilder: PREAUTH FAILED/REQ, re-send AS-REQ
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
Looking for keys for: HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
Added key: 18version: 12
Looking for keys for: HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
Added key: 18version: 12
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=dev.devdevelopment.com. UDP:88, timeout=30000, number of retries =3, #bytes=316
>>> KDCCommunication: kdc=dev.devdevelopment.com. UDP:88, timeout=30000,Attempt =1, #bytes=316
>>> KrbKdcReq send: #bytes read=108
>>> KrbKdcReq send: kdc=dev.devdevelopment.com. TCP:88, timeout=30000, number of retries =3, #bytes=316
>>> KDCCommunication: kdc=dev.devdevelopment.com. TCP:88, timeout=30000,Attempt =1, #bytes=316
>>>DEBUG: TCPClient reading 1766 bytes
>>> KrbKdcReq send: #bytes read=1766
>>> KdcAccessibility: remove dev.devdevelopment.com.:88
Looking for keys for: HTTP/windows7devpc.devdevelopment.com@DEVDEVELOPMENT.COM
Added key: 18version: 12
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsRep cons in KrbAsReq.getReply HTTP/windows7devpc.devdevelopment.com
New ticket is stored in cache file C:\Users\devtomcat\krb5cc_devtomcat

Ниже приведены переменные среды Java, которые устанавливаются на вкладке Java окна свойств Tomcat8:

И, наконец, ниже приведены настройки, сделанные в браузере Firefox на компьютере с Windows XP для пользователя домена devuser:-

Журналы Wireshark на компьютере tomcat не показывают никаких записей / действий при доступе к веб-приложению на компьютере с Windows XP. Я сомневаюсь, что переговоры SPNEGO инициируются машиной кота.

Должен ли файл krb5.ini находиться в каталоге C:\Windows? Также имеет значение пробелы в пути к файлу keytab?

Я следовал инструкциям, упомянутым здесь. Где и что я делаю неправильно / что-то упустил?

1 ответ

В jaas.conf, включают debug=true, поэтому он напечатает имя файла использованной таблицы ключей и другую полезную информацию.

Вы увидите, что имя файла keytab обрабатывается как экранированная строка Java, поэтому вы должны написать двойную обратную косую черту в качестве разделителей пути. Довольно сложный вопрос.

Другие вопросы по тегам