9

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

何が悪いのかわかりません...

4

2 に答える 2

6

Kerberos は、信頼できるサードパーティのセキュリティ システムです。クライアントから受け取ったセキュリティ トークンは、Kerberos インフラストラクチャ サーバー (KDC など) に接続することなく、自分だけが復号化できます。あなたは正しい道を進んでいます。ただし、今後の調​​査に役立つこの Kerberos の背景知識が不足しているようです。

これを実現する方法は、サーバーの秘密鍵を含むキータブファイルがサーバー上に必要であることです。Kerberos サーバー (おそらく Microsoft Windows Server) には、サービス用に作成されたサービス プリンシパル アカウントが必要です。管理者は、このアカウント用に生成されたキータブ ファイルを提供できます。このファイルには秘密鍵が含まれます。

次に、このキータブ ファイルを見つけるようにサーバーを構成する必要があります。を含むサーバー側のステップで使用されますLoginContext.login。セキュリティ コンテキストを受け入れるコードはdoPrivileged、サーバー側の資格情報が有効なコード セグメント内で実行する必要があります。

于 2013-01-16T09:09:21.360 に答える
-2

ユーザー名だけが必要な場合は、もっと簡単な方法があります。

request.getUserPrincipal().getName()

http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal() http://docs.oracle.com/javase/7/docs/api/java/security /プリンシパル.html

于 2013-06-04T00:01:59.317 に答える