JavaアプリケーションでWindows NTLM認証を使用してイントラネットユーザーを透過的に認証したい。ブラウザを使用している場合(シングルサインオン)、ユーザーは認証に気付かないはずです。
NTLMをサポートするいくつかのライブラリを見つけましたが、どのライブラリを使用すればよいかわかりません。
どこから始めるべきか?
上記のリストのうち、ntlmv2-authとJespaのみがNTLMv2をサポートしています。 Jespaは実行可能ですが、商用です。 ntlmv2-auth試したことはありませんが、これは以前に動作していたLiferayのコードに基づいています。
'ntlm-authentication-in-Java'はNTLMv1のみで、古くて安全ではなく、新しいバージョンのWindowsにアップグレードするにつれて、減少する環境で機能します。 JCIFSには以前はNTLMv1 HTTP認証フィルターがありましたが、それが実装された方法は安全でないプロトコルに対する中間者攻撃に相当するため、後のバージョンでは削除されました。 (同じことが「ntlm-authentication-in-Java」にも当てはまるようです。)
「spnego」プロジェクトは、NTLMではなくKerberosです。フルIWAをIISで複製する場合は、NTLMv2とKerberosの両方をサポートする必要があります(「NTLM」認証、「ネゴシエート」認証、NTLMSSP-in-SPNego認証、およびNTLM -masquerading-as-Negotiate auth)。
Luigi Dragoneのスクリプトは本当に古く、常に失敗するようです。
ライブラリ jcifs を追加すると、HttpURLConnectionはNTLMで動作します。この例は、最新の jcifs-1.3.18 で動作します。
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.net.HttpURLConnection;
import Java.net.URL;
import Java.net.UnknownHostException;
import Java.util.HashMap;
import Java.util.Map;
import org.Apache.http.impl.auth.NTLMEngineException;
public class TestNTLMConnection {
public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException {
// Method 1 : authentication in URL
jcifs.Config.registerSmbURLHandler();
URL urlRequest = new URL("http://domain%5Cuser:[email protected]/");
// or Method 2 : authentication via System.setProperty()
// System.setProperty("http.auth.ntlm.domain", "domain");
// System.setProperty("jcifs.smb.client.domain", "domain");
// System.setProperty("jcifs.smb.client.username", "user");
// System.setProperty("jcifs.smb.client.password", "pass");
// Not verified // System.setProperty("jcifs.netbios.hostname", "Host");
// System.setProperty("Java.protocol.handler.pkgs", "jcifs");
// URL urlRequest = new URL("http://127.0.0.1:8180/simulate_get.php");
HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();
StringBuilder response = new StringBuilder();
try {
InputStream stream = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
response.append(str);
}
in.close();
System.out.println(response);
} catch(IOException err) {
System.out.println(err);
} finally {
Map<String, String> msgResponse = new HashMap<String, String>();
for (int i = 0;; i++) {
String headerName = conn.getHeaderFieldKey(i);
String headerValue = conn.getHeaderField(i);
if (headerName == null && headerValue == null) {
break;
}
msgResponse.put(headerName == null ? "Method" : headerName, headerValue);
}
System.out.println(msgResponse);
}
}
}
また、各ハンドシェイクの内容に興味がある場合は、jcifsとSocketを使用して、この thread で別の例を見つけることができます。
参照: https://jcifs.samba.org/src/docs/faq.html#ntlmv2
Q:jCIFSはNTLMv2をサポートしていますか?
A:はい。 1.3.0以降、JCIFSはNTLMv2を完全にサポートし、デフォルトで使用します。
注:JCIFSに含まれていたNTLM HTTP SSOフィルターは、NTLMv2をサポートできません。
あなたが与えたリストから比較的、私は [〜#〜] jcifs [〜#〜] で行きます。ライブラリは成熟しており、ドキュメントは良好です。それを締めくくるために、彼らはかなり定期的なリリースをしました、そして最後のリリースは2011年11月でした。
Personal Experience
:私が試した他のもの(spnegoおよびntmv2auth)と比較すると、始めるのはかなり簡単でした。