2012-05-31 2 views
4

Мне нужно написать программу, которая проверяет защищенный сайт Kerberos нашей компании. Я стараюсь его HttpClient и получить следующее сообщение об ошибке:HttpClient проверяет защищенную веб-страницу Kerberos. Логин NTLM не работал

KrbException: Server not found in Kerberos database (7) 
    at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:61) 
    at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:185) 
     ... 

Я написал NTLM вход 5 месяцев назад, но он не работает для этого защищенного сайта Kerberos. Я думаю, что Nego2 активирован, поэтому он не возвращается к NTLM, если Kerberos терпит неудачу.

Я читал статью в Kerberos Wikipedia: http://en.wikipedia.org/wiki/Kerberos_(protocol), и я думаю, проблема в том, что TGS не находит запрошенную услугу в базе данных. Я думаю, это потому, что я получаю билет до ошибки (я думаю, что это TGT).

Found ticket for [email protected] to go to krbtgt/[email protected] expiring on Thu May 31 01:35:56 CEST 2012 

Так что ошибка whould произойдет в «Client Service Authorization» -> 2. (см статью в Википедии)

Проблема заключается в том, что услуга должна быть в базе данных Kerberos, потому что я могу получить доступ к он с IE (без входа в систему, поэтому работает один знак).

Так что мой вопрос: Почему TGS не находит сервер в базе данных Kerberos, но он работает с IE?


Экстренная Информация
Я пытался получить необходимую информацию на вершине, но здесь вся информация, потому что я не знаю, если я получил всю необходимую информацию:

ОС Windows 7
Firefox версии 9.0.1
Chrome версии 19.0.1084.52
Safari версии 5.0.2
IE версии 8.0.7600.16385

Мои Java Код:

System.setProperty("java.security.auth.login.config", "file://c:/temp/jaas.conf"); 
    System.setProperty("java.security.krb5.conf", "c:/winnt/krb5.ini"); 
    System.setProperty("sun.security.krb5.debug", "true"); 
    System.setProperty("javax.security.auth.useSubjectCredsOnly","false"); 

    DefaultHttpClient httpclient = new DefaultHttpClient(); 
    try { 
     httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory()); 

     Credentials use_jaas_creds = new Credentials() { 

      public String getPassword() { 
       return null; 
      } 

      public Principal getUserPrincipal() { 
       return null; 
      } 

     }; 

     httpclient.getCredentialsProvider().setCredentials(
       new AuthScope(null, -1, null), 
       use_jaas_creds); 

     HttpUriRequest request = new HttpGet("url.com:port/site"); //Kerberos secured url 
     HttpResponse response = httpclient.execute(request); 
     HttpEntity entity = response.getEntity(); 

     System.out.println("----------------------------------------"); 
     System.out.println(response.getStatusLine()); 
     System.out.println("----------------------------------------"); 
     if (entity != null) { 
      System.out.println(EntityUtils.toString(entity)); 
     } 
     System.out.println("----------------------------------------"); 

     // This ensures the connection gets released back to the manager 
     EntityUtils.consume(entity); 

jaas.conf

com.sun.security.jgss.login { 
com.sun.security.auth.module.Krb5LoginModule required client=TRUE; 
}; 
com.sun.security.jgss.initiate { 
com.sun.security.auth.module.Krb5LoginModule required client=TRUE; 
}; 
com.sun.security.jgss.accept { 
com.sun.security.auth.module.Krb5LoginModule required client=TRUE; 
}; 

krb5.ini

[logging] 
default = FILE:log/krb5libs.log 
kdc = FILE:log/krb5kdc.log 
admin_server = FILE:log/kadmind.log 

[libdefaults] 
ticket_lifetime = 24000 
default_realm = EXAMPLE.COM 
dns_lookup_realm = false 
dns_lookup_kdc = false 

[realms] 
EXAMPLE.COM = { 
    kdc = url 
    admin_server = url 
} 

[domain_realm] 
url.com = EXAMPLE.COM 

[kdc] 
profile = /var/kerberos/krb5kdc/kdc.conf 

[appdefaults] 
pam = { 
    debug = false 
    ticket_lifetime = 36000 
    renew_lifetime = 36000 
    forwardable = true 
    krb4_convert = false 
} 

Hole Log файл из теста:

log4j:WARN No appenders could be found for logger (org.apache.http.impl.conn.BasicClientConnectionManager). 
log4j:WARN Please initialize the log4j system properly. 
Kerberos-Benutzername [user]: user 
Kerberos-Passwort für user: ******* 
Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17. 
Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17. 
>>> KrbAsReq calling createMessage 
>>> KrbAsReq in createMessage 
>>> KrbKdcReq send: kdc=kdcurl UDP:88, timeout=30000, number of retries =3, #bytes=155 
>>> KDCCommunication: kdc=kdcurl UDP:88, timeout=30000,Attempt =1, #bytes=155 
>>> KrbKdcReq send: #bytes read=220 
>>> KrbKdcReq send: #bytes read=220 
>>> KDCRep: init() encoding tag is 126 req type is 11 
>>>KRBError: 
    sTime is Thu May 31 08:46:29 CEST 2012 1338446789000 
    suSec is 51983 
    error code is 25 
    error Message is Additional pre-authentication required 
    realm is EXAMPLE.COM 
    sname is krbtgt/EXAMPLE.COM 
    eData provided. 
    msgType is 30 
>>>Pre-Authentication Data: 
    PA-DATA type = 11 
    PA-ETYPE-INFO etype = 23 
>>>Pre-Authentication Data: 
    PA-DATA type = 2 
    PA-ENC-TIMESTAMP 
>>>Pre-Authentication Data: 
    PA-DATA type = 15 
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ 
Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17. 
Pre-Authentication: Set preferred etype = 23 
>>>KrbAsReq salt is EXAMPLE.COMuser 
Pre-Authenticaton: find key for etype = 23 
AS-REQ: Add PA_ENC_TIMESTAMP now 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KrbAsReq calling createMessage 
>>> KrbAsReq in createMessage 
>>> KrbKdcReq send: kdc=kdcurl UDP:88, timeout=30000, number of retries =3, #bytes=219 
>>> KDCCommunication: kdc=kdcurl UDP:88, timeout=30000,Attempt =1, #bytes=219 
>>> KrbKdcReq send: #bytes read=100 
>>> KrbKdcReq send: #bytes read=100 
>>> KDCRep: init() encoding tag is 126 req type is 11 
>>>KRBError: 
    sTime is Thu May 31 08:46:29 CEST 2012 1338446789000 
    suSec is 114485 
    error code is 52 
    error Message is Response too big for UDP, retry with TCP 
    realm is EXAMPLE.COM 
    sname is krbtgt/EXAMPLE.COM 
    msgType is 30 
>>> KrbKdcReq send: kdc=kdcurl TCP:88, timeout=30000, number of retries =3, #bytes=219 
>>>DEBUG: TCPClient reading 3277 bytes 
>>> KrbKdcReq send: #bytes read=3277 
>>> KrbKdcReq send: #bytes read=3277 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KrbAsRep cons in KrbAsReq.getReply user 
Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17. 
Found ticket for [email protected] to go to krbtgt/[email protected] expiring on Thu May 31 18:46:29 CEST 2012 
Entered Krb5Context.initSecContext with state=STATE_NEW 
Service ticket not found in the subject 
>>> Credentials acquireServiceCreds: same realm 
Using builtin default etypes for default_tgs_enctypes 
default etypes for default_tgs_enctypes: 3 1 23 16 17. 
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType 
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType 
>>> KrbKdcReq send: kdc=kdcurl UDP:88, timeout=30000, number of retries =3, #bytes=3298 
>>> KDCCommunication: kdc=kdcurl UDP:88, timeout=30000,Attempt =1, #bytes=3298 
>>> KrbKdcReq send: #bytes read=110 
>>> KrbKdcReq send: #bytes read=110 
>>> KDCRep: init() encoding tag is 126 req type is 13 
>>>KRBError: 
    sTime is Thu May 31 08:46:29 CEST 2012 1338446789000 
    suSec is 192613 
    error code is 7 
    error Message is Server not found in Kerberos database 
    realm is EXAMPLE.COM 
    sname is HTTP/url.com:port 
    msgType is 30 
KrbException: Server not found in Kerberos database (7) 
    at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:61) 
    at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:185) 
    at sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:294) 
    at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:106) 
    at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:562) 
    at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:594) 
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:230) 
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162) 
    at sun.security.jgss.spnego.SpNegoContext.GSS_initSecContext(SpNegoContext.java:851) 
    at sun.security.jgss.spnego.SpNegoContext.initSecContext(SpNegoContext.java:309) 
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:230) 
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162) 
    at org.apache.http.impl.auth.GGSSchemeBase.generateGSSToken(GGSSchemeBase.java:99) 
    at org.apache.http.impl.auth.SPNegoScheme.generateToken(SPNegoScheme.java:80) 
    at org.apache.http.impl.auth.GGSSchemeBase.authenticate(GGSSchemeBase.java:155) 
    at org.apache.http.impl.auth.SPNegoScheme.authenticate(SPNegoScheme.java:75) 
    at org.apache.http.client.protocol.RequestAuthenticationBase.authenticate(RequestAuthenticationBase.java:125) 
    at org.apache.http.client.protocol.RequestAuthenticationBase.process(RequestAuthenticationBase.java:83) 
    at org.apache.http.client.protocol.RequestTargetAuthentication.process(RequestTargetAuthentication.java:80) 
    at org.apache.http.protocol.ImmutableHttpProcessor.process(ImmutableHttpProcessor.java:109) 
    at org.apache.http.protocol.HttpRequestExecutor.preProcess(HttpRequestExecutor.java:176) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:516) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) 
    at mypackage.ClientKerberosAuthentication.main(ClientKerberosAuthentication.java:152) 
Caused by: KrbException: Identifier doesn't match expected value (906) 
    at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133) 
    at sun.security.krb5.internal.TGSRep.init(TGSRep.java:58) 
    at sun.security.krb5.internal.TGSRep.<init>(TGSRep.java:53) 
    at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:46) 
    ... 25 more 
---------------------------------------- 
HTTP/1.1 401 Unauthorized 
---------------------------------------- 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Draft//EN"> 
<HTML> 
<HEAD> 
<TITLE>Error 401--Unauthorized</TITLE> 
</HEAD> 
<BODY bgcolor="white"> 
<FONT FACE=Helvetica><BR CLEAR=all> 
<TABLE border=0 cellspacing=5><TR><TD><BR CLEAR=all> 
<FONT FACE="Helvetica" COLOR="black" SIZE="3"><H2>Error 401--Unauthorized</H2> 
</FONT></TD></TR> 
</TABLE> 
<TABLE border=0 width=100% cellpadding=10><TR><TD VALIGN=top WIDTH=100% BGCOLOR=white><FONT FACE="Courier New"><FONT FACE="Helvetica" SIZE="3"><H3>From RFC 2068 <i>Hypertext Transfer Protocol -- HTTP/1.1</i>:</H3> 
</FONT><FONT FACE="Helvetica" SIZE="3"><H4>10.4.2 401 Unauthorized</H4> 
</FONT><P><FONT FACE="Courier New">The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.46) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity MAY include relevant diagnostic information. HTTP access authentication is explained in section 11.</FONT></P> 
</FONT></TD></TR> 
</TABLE> 

</BODY> 
</HTML> 

---------------------------------------- 
+0

Я написал на альтернативное решение для этого здесь: http://stackoverflow.com/a/22865583/381161 –

ответ

4

Это не сработает.

  1. В Active Directory не используются порты в SPN. Не знаю, где этот глупый материал попал в HttpClient.
  2. SPN не зарегистрирован для вашего целевого хоста в вашем Active Directory.

Ответы на вопросы:

  1. Вовсе нет, только service class and hostname are mandatory. Класс сервиса уже идентифицирует службу, с которой зарегистрирован порт, например. LDAP, HTTP, FTP и т. Д. У нас есть сотни тысяч SPN в нашем лесу. Ни один из них с портами.Например, я бы выполнил огромную работу по регистрации каждого экземпляра порта HTTP-сервера. AD должен знать только целевой хост. Он соответствующим образом зашифрует служебный билет. Это делает его уникальным.
  2. Зачем браузеру не удается? Он создает SPN как HTTP/<FQDN>. Пока это существует в каталоге, все будет идти гладко.

Когда я попробовал HTTPClient, я никогда не был доволен дерьмовой поддержкой SPNEGO. Я хотел бы переписать этот материал, когда я возьмусь за руки.

+0

1. Я думал, что SPN состоит класс обслуживания, хост и порт , И что эти три вещи делают его уникальным. Итак, как AD может не иметь порт для SPN и все еще знать, что это такое? 2. Если это не так, доступ к веб-браузеру также не может быть неудачным, поскольку он не может найти SPN в активном каталоге? Но я могу получить доступ к сервису в IE, FF и Chrome. – SCBoy

+0

Отметьте мое редактирование выше. –

+0

ОК спасибо :) Но я все еще не там. Я не понимаю, что с httpclient я получаю сообщение об ошибке сервера, но я могу получить доступ к службе через веб-браузер, поэтому сервер находится в базе данных объявлений. Так HttpClient строит SPN неправильно? Или что я забыл? – SCBoy

2

Я нашел способ решить эту проблему.
Просто добавьте параметр (true) к конструктору объекта SPNegoSchemeFactory.


    httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory(true)); 

Это сделает ваш SNAME HTTP/url.com: порт к HTTP/url.com.
Благодаря этому JIRA: https://issues.apache.org/jira/browse/HTTPCLIENT-966?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

2

Я создал небольшой инструмент для упрощения не соединяясь с HTTPClient 3 к Керберосу (нет внешних конфигурационных файлов), вы можете дать ему попробовать. https://github.com/DovAmir/httpclientAuthHelper

DefaultHttpClient httpclient = new DefaultHttpClient(); 
AuthUtils.securityLogging(SecurityLogType.KERBEROS,true); 
CredentialsUtils.setKerberosCredentials(client, new UsernamePasswordCredentials("xxx", "xxx"), "domain", "kdc"); 
client.executeMethod(httpget); 
Смежные вопросы