HTTP SPNEGOは、HTTP通信でNegotiate認証スキームをサポートしています。SPNEGOは、次のタイプの認証をサポートしています。
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.....
これにより、クライアントはプロキシ・サーバーの認証を受けます。
この機能は、両方のタイプの認証をサポートしています。
新規の機能に関連して新しく公開されたAPI関数はありません。ただし、正しく通信を行うには、いくつかの構成を行う必要があります。
SPNEGOメカニズムはJGSSを呼び出し、JGSSは実際の作業を行うためにKerberos V5ログイン・モジュールを呼び出します。Kerberos 5を構成する必要があります。次のものが必要となります。
java.security.krb5.conf
を使用して実現できます。たとえば、java -Djava.security.krb5.conf=krb5.conf \ -Djavax.security.auth.useSubjectCredsOnly=false \ ClassName
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が選択されるため、Kerberosはこのリストには示されていません。
サーバーがNegotiateを含む複数の認証方式を提供している場合、前述のセクションで説明されている処理順序に従って、JavaはNegotiateスキームを試行します。ただし、このプロトコルが正常に確立されない場合(たとえば、kerberos構成が正しくない、サーバーのホスト名がKDCプリンシパルDBに記録されていない、オーセンティケータによって指定されたユーザー名とパスワードが間違っているなど)、2番目に強力なスキームが自動的に使用されます。
注:http.auth.preference
がSPNEGOまたはKerberosに設定されている場合、SPNEGOでは、失敗する場合でもネゴシエーション・スキームのみを試行すると見なされます。SPNEGOはその他のスキームにフォール・バックしません。プログラムはIOException
をスローし、HTTP応答から401または407エラーを受信したことを通知します。
保護されているファイルを取得するには、次のファイルを準備する必要があります。
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; };
次に、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>