AuthorizationHTTPヘッダーのKerberosチケットからユーザーの名前を読み取りたい。私はJavaを使用しています。
私はこの主題に関するたくさんのサイトを読んでこれを達成しようと何日も費やしましたが、これを行うことができませんでした。Kerberosは私にとって新しい/外国のものです。
これは私が達成したことです:
- ユーザーが最初にサイトにアクセスすると、Authorizationヘッダーなしで、サーバーは401 +ヘッダーで応答します:WWW-Authenticate=Negotiate。
- あらゆる種類の魔法のことがクライアント側で起こります。
- ユーザーは、次のような値のAuthorizationヘッダーを含むHTTPリクエストで戻ります: "Negotiate YHcGB ... =="
- base64でエンコードされたチケットをバイト配列にデコードします。
ここからは、未知の世界を旅する恐ろしい旅です。私の知る限り、次のステップは次のようになります。
- ユーザーを使用してAD/Kerberos/サーバーにログインします。
- チケットをデコードします。
これは私が持っているものです:
login.conf
ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/some.server.com@MY.DOMAIN.COM"
doNotPrompt=true
useTicketCache=true
password=mYpasSword
debug=true;
};
JavaClass.java
String encodedTicket = authorization.substring("Negotiate ".length());
byte[] ticket = Base64.decode(encodedTicket);
LoginContext lc = new LoginContext("ServicePrincipalLoginContext");
lc.login();
Subject serviceSubject = lc.getSubject();
Subject.doAs(serviceSubject, new ServiceTicketDecoder(ticket));
ServiceTicketDecoder.java
public String run() throws Exception {
Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");
GSSManager gssManager = GSSManager.getInstance();
String service = "krbtgt/MY.DOMAIN.COM@MY.DOMAIN.COM";
GSSName serviceName = gssManager.createName(service, GSSName.NT_USER_NAME);
GSSCredential serviceCredentials = gssManager.createCredential(serviceName, GSSCredential.INDEFINITE_LIFETIME, kerberos5Oid, GSSCredential.ACCEPT_ONLY);
GSSContext gssContext = gssManager.createContext(serviceCredentials);
gssContext.acceptSecContext(this.serviceTicket, 0, this.serviceTicket.length);
GSSName srcName = gssContext.getSrcName();
return srcName.toString;
}
JavaClass.javaでのログインは問題なく機能するため、login.confは問題ないと想定しています。ServiceTicketDecoder.javaの「GSSCredentialserviceCredentials=gssManager.createCredential(...」」で、次の例外がスローされます。
java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)
これが正しいアプローチかどうかはわかりません。また、「文字列サービス」の価値やその情報の取得方法もわかりません。手伝って頂けますか?
編集:login.conf
ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/some.server.com@MY.DOMAIN.COM"
doNotPrompt=true
useTicketCache=true
keyTab="C:/server-http.keytab"
debug=true;
};
キータブファイルを受け取りました。どうやら、HTTP/some.server.comユーザーのアカウントはすでにサービスプリンシパルアカウントでした。lc.login()のJavaClass.javaで問題が発生しました。
javax.security.auth.login.LoginException: KDC has no support for encryption type (14)
Caused by: KrbException: KDC has no support for encryption type (14)
Caused by: KrbException: Identifier doesn't match expected value (906)
keytabファイルはdes-cbc-md5で暗号化されており、krb.confファイルで次のように定義されています。
[libdefaults]
default_realm = MY.DOMAIN.COM
default_tkt_enctypes = des-cbc-md5
default_tgs_enctypes = des-cbc-md5
デフォルトのenctypesをたとえばaes128-ctsに変更すると、次の例外が発生します。
javax.security.auth.login.LoginException: Do not have keys of types listed in default_tkt_enctypes available; only have keys of following type: DES CBC mode with MD5
何が悪いのかわかりません...