プライマリ・コンテンツに移動
Java Platform, Standard Editionセキュリティ開発者ガイド
リリース10
E94999-01
目次へ移動
目次

前
次
次へ

第VI部: HTTP/SPNEGO認証

課題9: HTTP/SPNEGO認証の使用

HTTP SPNEGOとは

HTTP SPNEGOは、HTTP通信でNegotiate認証スキームをサポートしています。SPNEGOは、次のタイプの認証をサポートしています。

Web認証

Webサーバーは次のように応答します。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Negotiate

クライアントは、次のヘッダーを送信する必要があります。

Authorization: Negotiate YY.....

これにより、クライアントはサーバーの認証を受けます。

プロキシ認証

Webサーバーは次のように応答します。

HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Negotiate

クライアントは、次のヘッダーを送信する必要があります。

Proxy-Authorization: Negotiate YY.....

これにより、クライアントはプロキシ・サーバーの認証を受けます。

この機能は、両方のタイプの認証をサポートしています。

HTTP/SPNEGO認証の使用方法

新規の機能に関連して新しく公開されたAPI関数はありません。ただし、正しく通信を行うには、いくつかの構成を行う必要があります。

Kerberos 5の構成

SPNEGOメカニズムはJGSSを呼び出し、JGSSは実際の作業を行うためにKerberos V5ログイン・モジュールを呼び出します。Kerberos 5を構成する必要があります。次のものが必要となります。

  • Kerberos構成を指定する手段。これは、Javaシステム・プロパティjava.security.krb5.confを使用して実現できます。次に例を示します。

    java -Djava.security.krb5.conf=krb5.conf \
         -Djavax.security.auth.useSubjectCredsOnly=false \
         ClassName

    使用するログイン・モジュールを示すJAAS構成ファイル。HTTP SPNEGOコードは、com.sun.security.jgss.krb5.initiateという名前の標準エントリを検索します。

    たとえば、次のようにファイルspnegoLogin.confを指定できます。

    com.sun.security.jgss.krb5.initiate {
        com.sun.security.auth.module.Krb5LoginModule
            required useTicketCache=true;
    };

    次のようにjavaを実行します。

    java -Djava.security.krb5.conf=krb5.conf \
         -Djava.security.auth.login.config=spnegoLogin.conf \
         -Djavax.security.auth.useSubjectCredsOnly=false \
         ClassName

ユーザー名およびパスワードの取得

他のHTTP認証スキームと同じように、必要に応じて、クライアントはカスタマイズされたjava.net.Authenticatorを指定してHTTP SPNEGOモジュールにユーザー名とパスワードを指定できます(つまり、資格キャッシュは使用できません)。オーセンティケータでチェックする必要がある認証情報は、getRequestingScheme()を使用して取得可能なスキームのみです。値は「Negotiate」である必要があります。

つまり、オーセンティケータ実装は次のようになります。

class MyAuthenticator extends Authenticator {

        public PasswordAuthentication getPasswordAuthentication () {
            if (getRequestingScheme().equalsIgnoreCase("negotiate")) {
                String krb5user;
                char[] krb5pass;
                // get krb5user and krb5pass in your own way
                ....
                return (new PasswordAuthentication (krb5user,
                            krb5pass));
            } else {
                ....
            }
        }
    }

注意:

java.net.Authenticatorの仕様では、ユーザー名とパスワードを同時に取得するように設計されています。このため、JAAS構成ファイルにprincipal=xxxを指定しないでください。

スキームの優先設定

クライアントは、システム・プロパティhttp.auth.preferenceを指定して、サーバーが特定のスキームを要求するかぎりそのスキームが常に使用されるように指定できます。このシステム・プロパティに対して「SPNEGO」または「Kerberos」を使用できます。「SPNEGO」は、GSS/SPNEGOメカニズムを使用してネゴシエーション・スキームに応答します。「Kerberos」は、GSS/Kerberosメカニズムを使用してネゴシエーション・スキームに応答します。通常、Microsoft製品に対して認証を行う場合に「SPNEGO」を使用できます。値「Kerberos」もMicrosoftサーバーに対して動作します。これは、ネゴシエーションは認識するがSPNEGOは認識しないサーバーに対してのみ使用する必要があります。

http.auth.preferenceが設定されていない場合、選択される内部順序は次のようになります。

  • GSS/SPNEGO ->ダイジェスト -> NTLM ->基本

ネゴシエーションがサポートされる場合は常にGSS/SPNEGOが選択されるため、Kerberosはこのリストには示されていません。

フォール・バック

サーバーがNegotiateを含む複数の認証方式を提供している場合、前述のセクションで説明されている処理順序に従って、JavaはNegotiateスキームを試行します。ただし、このプロトコルが正常に確立されない場合(たとえば、Kerberos構成が正しくない、サーバーのホスト名がKDCプリンシパルDBに記録されていない、オーセンティケータによって指定されたユーザー名とパスワードが間違っているなど)、2番目に強力なスキームが自動的に使用されます。

注意:

http.auth.preferenceがSPNEGOまたはKerberosに設定されている場合、SPNEGOでは、失敗する場合でもネゴシエーション・スキームのみを試行すると見なされます。SPNEGOはその他のスキームにフォール・バックしません。プログラムはIOExceptionをスローし、HTTP応答から401または407エラーを受信したことを通知します。

HTTP/SPNEGO認証の例

Active Directory内のWindowsサーバーでIISサーバーを実行しているとします。このサーバー上のWebページは、統合Windows認証によって保護されるように構成されています。つまり、サーバーはネゴシエーションとNTLMの両方の認証を要求します。

保護されているファイルを取得するには、次のファイルを準備する必要があります。

RunHttpSpnego.java

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;

public class RunHttpSpnego {

    static final String kuser = "username"; // your account name
    static final String kpass = "password"; // your password for the account

    static class MyAuthenticator extends Authenticator {
        public PasswordAuthentication getPasswordAuthentication() {
            // I haven't checked getRequestingScheme() here, since for NTLM
            // and Negotiate, the usrname and password are all the same.
            System.err.println("Feeding username and password for " + getRequestingScheme());
            return (new PasswordAuthentication(kuser, kpass.toCharArray()));
        }
    }

    public static void main(String[] args) throws Exception {
        Authenticator.setDefault(new MyAuthenticator());
        URL url = new URL(args[0]);
        InputStream ins = url.openConnection().getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
        String str;
        while((str = reader.readLine()) != null)
            System.out.println(str);
    }
}

krb.conf

[libdefaults]
    default_realm = AD.LOCAL
[realms]
    AD.LOCAL = {
        kdc = kdc.ad.local
    }

login.conf

com.sun.security.jgss.krb5.initiate {
  com.sun.security.auth.module.Krb5LoginModule required  doNotPrompt=false useTicketCache=true;
};

サンプルのコンパイルおよび実行

  1. RunHttpSpnego.javaをコンパイルします。

  2. RunHttpSpnego.javaを実行します。

    java -Djava.security.krb5.conf=krb5.conf \
        -Djava.security.auth.login.config=login.conf \
        -Djavax.security.auth.useSubjectCredsOnly=false \
        RunHttpSpnego \
        http://www.ad.local/hello/hello.html

    次の出力が表示されます。

    Feeding username and password for Negotiate 
    <h1>Hello, You got me!</h1>

    ドメイン・ユーザーとしてWindowsマシン上で実行しているか、またはすでにkinitコマンドを発行して資格キャッシュを取得しているLinuxかSolarisマシン上で実行している場合は、次のようになります。クラスMyAuthenticatorは完全に無視され、出力は次のようになります:

    <h1>Hello, You got me!</h1>

    これは、ユーザー名とパスワードが参照されないことを示しています。これはシングル・サインオンと呼ばれます。

    また、次のように実行して、

    java RunHttpSpnego http://www.ad.local/hello/hello.html

    フォール・バックがどのように実行されるかを確認できます。この場合は、次のように表示されます。

    Feeding username and password for ntlm
    <h1>Hello, You got me!</h1>