…ためには色々面倒な実装が必要なのかと調べてみれば、実はそうでもなかった、というお話。
[ディレクトリセキュリティ(ファイルセキュリティ)] -> 認証とアクセス制御の[編集] ->
[匿名アクセスを有効にする]のチェックを外し、[総合 Windows 認証]にチェックを入れる。
この状態でブラウザからアクセスするとユーザ名、パスワードを入力させる認証ダイアログが表示される。
NTLM 認証の設定
IIS マネージャでファイルもしくはディレクトリのプロパティを開き、[ディレクトリセキュリティ(ファイルセキュリティ)] -> 認証とアクセス制御の[編集] ->
[匿名アクセスを有効にする]のチェックを外し、[総合 Windows 認証]にチェックを入れる。
この状態でブラウザからアクセスするとユーザ名、パスワードを入力させる認証ダイアログが表示される。
Commons HttpClient で NTLM 認証に対応する
Commons HttpClient (3系)で NTLM 認証に対応するには、NTCredentials を使用する。サーバに対する NTLM 認証に対応するには以下のようにする。
public void ntlmExecute() throws IOException {
HttpClient client = new HttpClient();
client.getState().setCredentials(
new AuthScope(SCOPE_HOST, SCOPE_PORT),
new NTCredentials(USERNAME, PASSWORD, HOST, DOMAIN));
HttpMethod method = new PostMethod(URL);
int result = client.executeMethod(method);
System.out.println(result);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
for (String line = reader.readLine() ; line != null ; line = reader.readLine()) {
System.out.println(line);
}
} finally {
if (reader != null) reader.close();
}
}
プロキシサーバに対する NTLM 認証に対応するには以下のようにする。
public void ntlmProxyExecute() throws IOException {
HttpClient client = new HttpClient();
client.getHostConfiguration().setProxy(PROXY_HOST, PROXY_PORT);
client.getState().setProxyCredentials(
new AuthScope(SCOPE_HOST, SCOPE_PORT),
new NTCredentials(USERNAME, PASSWORD, HOST, DOMAIN));
HttpMethod method = new GetMethod(URL);
int result = client.executeMethod(method);
System.out.println(result);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
for (String line = reader.readLine() ; line != null ; line = reader.readLine()) {
System.out.println(line);
}
} finally {
if (reader != null) reader.close();
}
}
SOAP Webサービスクライアントを作ろう(Apache Axis 編)で書いた通り、HTTP1.1 に対応させるために Commons HttpClient を使用したため、
上のコードを応用すれば Axis でもイケるだろうか…と調べてみた。
Apache Axis で NTLM 認証に対応する
NTLM 認証が設定されたエンドポイントに対してリクエストを送ると、以下のフォルトが返る。
- ntlm authentication scheme selected
- No credentials available for NTLM @<ホスト>:<ポート>
Exception in thread "main" AxisFault
faultCode: {http://xml.apache.org/axis/}HTTP
faultSubcode:
faultString: (401)Unauthorized
faultActor:
faultNode:
faultDetail:
CommonsHTTPSender から何とか HttpState を取り出して NTCredentials をセットできないものかとCommonsHTTPSender のソースを眺めてみたところ、
既に NTCredentials をセットするコードが含まれていた。
MessageContext にセットされたユーザ名がドメインを含む表記だった場合、NTLM 認証用とみなしているようだ。
さらに、プロキシサーバの場合は TransportClientProperties からユーザ名などを取得していて、
実装クラス DefaultHTTPTransportClientProperties を見てみると
システムプロパティ「http.proxyHost」「http.proxyPort」「http.proxyUser」「http.proxyPassword」から値を参照しているため、
システムプロパティに適切な値を設定してあげれば Webサービスクライアント側のコードの変更は不要なようだ。
サーバに対する NTLM 認証に対応するのであれば、
自動生成したスタブを使用する場合、独自に SOAP リクエストを構築する場合でそれぞれ設定箇所が異なるが、
いずれにしてもユーザ名、パスワードを設定するだけで特別な処理は不要だった。
スタブを使用する場合
スタブを使用しない場合
設定が必要なのはユーザ名、パスワード、ドメインのみ。(「ドメイン\ユーザ名」の形でユーザ名にセットする)NTCredentials にセットするホスト名は CommonsHTTPSender 内部で NetworkUtils を使用して取得してくれるので、
外部から設定する必要はない。