我正在尝试使用其内置支持为Tomcat8.0 webapps实现Windows身份验证。我在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
以下是我的环境细节: -
我有一个域用户devtomcat,以下SPN映射到:
我有另一个域用户devuser,它是名为tc-webapp-users的组的成员,该组位于名为tomcat-ou的OU中。该用户用于从windows xp机器访问webapp。
以下是我的tomcat的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>
以下是webapp的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/[email protected]"
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/[email protected]"
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/[email protected]
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/[email protected]
>>>KinitOptions cache name is C:\Users\devtomcat\krb5cc_devtomcat
Principal is HTTP/[email protected]
>>> 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/[email protected]
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/[email protected]
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/[email protected]
Added key: 18version: 12
Looking for keys for: HTTP/[email protected]
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/[email protected]
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
以下是在Tomcat8属性窗口的Java选项卡中设置的Java环境变量: -
最后,以下是在域用户devuser的Windows xp机器上的Firefox浏览器中完成的设置: -
在Windows XP机器中访问webapp时,tomcat机器中的Wireshark登录不显示任何条目/活动。我怀疑是否由tomcat机器启动了SPNEGO协商。
krb5.ini文件应该放在C:\ Windows目录中吗?此外,keytab文件路径中的空格是否重要?
我按照here提到的说明进行操作。在哪里以及我做错了什么/遗失了什么?
在jaas.conf
中,包含debug=true
,因此它将打印使用过的keytab文件名和其他有用的信息。
您将看到keytab文件名作为转义的java字符串处理,因此您应该将双反斜杠写为路径分隔符。相当棘手的问题。