JCIFS NTLM库的替代品

有没有JCIFS NTLM库的替代品?

华夫饼 – https://github.com/dblock/waffle

具有filter,身份validation器,支持spring-security等。仅限Windows,但不需要本机DLL。

说实话,你不应该找一个。 对于您的SSO需求,您应该使用适当的kerberos / SPNEGO而不是传统的NTLM。

对于那些东西,你不需要特殊的库,因为JVM已经被自动启用了。 您所要做的就是正确配置应用程序和JVM安全策略。 Sun的官方文档应该为您提供所需的所有详细信息,只需浏览“安全API”部分即可。

实际上jcifs很好,您可以使用Windows IIS和一个保持活动的Java Socket在本地轻松测试4次握手 。

这个2004年的Apache 伪代码对于使用generateType1Msg()generateType3Msg()使用jcifs构建算法非常有用,甚至Apache也提供了一个示例来替代HttpClient。

2004年的旧Apache代码可以工作,但身份validation不稳定,你经常获得HTTP/1.1 401 Unauthorized ,这个来自Luigi Dragone的旧代码也不再适用了。 另一方面,Apache的HttpClient运行顺利,但握手是在场景后完成的( new NTCredentials()需要new NTCredentials()来定义用户的身份validation)。

下面是在没有域的端口81上在IIS上本地测试握手的示例。 您需要适当地更改hostportuserpassword以及HTTP标头,如果您不使用IIS,最终需要进行WWW-Authenticate

HTTP/1.1 200 OK表示身份validation正确,否则您将获得HTTP/1.1 401 Unauthorized

 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; import jcifs.ntlmssp.NtlmFlags; import jcifs.ntlmssp.Type1Message; import jcifs.ntlmssp.Type2Message; import jcifs.ntlmssp.Type3Message; import jcifs.util.Base64; import org.apache.http.impl.auth.NTLMEngineException; public class TestNTLM { public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException { Socket s = new Socket("127.0.0.1", 81); s.setKeepAlive(true); InputStream is = s.getInputStream(); OutputStream os = s.getOutputStream(); BufferedReader r = new BufferedReader(new InputStreamReader(is)); BufferedWriter w = new BufferedWriter(new OutputStreamWriter(os)); String host = "127.0.0.1:81"; String hostDomain = ""; String user = "My_Windows_Username"; String password = "My_Windows_Password"; w.write("GET http://127.0.0.1:81/ HTTP/1.1\n"); w.write("Host: 127.0.0.1:81\n"); w.write("Authorization: NTLM " + TestNTLM.generateType1Msg(hostDomain, host) + "\n\n"); System.out.println("[First Message Sent]"); w.flush(); String resp = "", line = ""; int contentLength = 0; while((line = r.readLine()) != null){ if(line.length() == 0) break; System.out.println(line); if(line.startsWith("Content-Length")) contentLength = Integer.parseInt(line.substring(line.indexOf(":") + 1).trim()); else if(line.startsWith("WWW-Authenticate")) resp = line.substring(line.indexOf(":") + 1).trim(); } r.skip(contentLength); System.out.println("\n[Second Message Received]"); System.out.println("Proxy-Authenticate: " + resp); resp = resp.substring(resp.indexOf(" ")).trim(); w.write("GET http://127.0.0.1:81/ HTTP/1.1\n"); w.write("Host: 127.0.0.1:81\n"); w.write("Authorization: NTLM " + TestNTLM.generateType3Msg(user, password, hostDomain, host, new String(resp)) + "\n\n"); w.flush(); System.out.println("\n[Third Message Sent]"); while((line = r.readLine()) != null){ System.out.println(line); if(line.length() == 0) break; } } private static final int TYPE_1_FLAGS = NtlmFlags.NTLMSSP_NEGOTIATE_56 | NtlmFlags.NTLMSSP_NEGOTIATE_128 | NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 | NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NtlmFlags.NTLMSSP_REQUEST_TARGET; public static String generateType1Msg(final String domain, final String workstation) throws NTLMEngineException { final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation); return Base64.encode(type1Message.toByteArray()); } public static String generateType3Msg(final String username, final String password, final String domain, final String workstation, final String challenge) throws NTLMEngineException { Type2Message type2Message; try { type2Message = new Type2Message(Base64.decode(challenge)); } catch (final IOException exception) { throw new NTLMEngineException("Invalid NTLM type 2 message", exception); } final int type2Flags = type2Message.getFlags(); final int type3Flags = type2Flags & (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER)); final Type3Message type3Message = new Type3Message(type2Message, password, domain, username, workstation, type3Flags); return Base64.encode(type3Message.toByteArray()); } } 

我认为NTLM正在被弃用以支持Kerberos / SPNEGO。 查看SPNEGO HTTP Servlet Filter项目,看看它是否符合您的需求。

Java Opensource单点登录(JOSSO)位于http://www.josso.org/他们在NTLM上有一个页面,虽然我不确定它的工作原理。

如果您不介意商业打包产品,请查看: Quest Single Sign On for Java ,它提供对SPNEGO / Kerberos(包括站点和S4U协议)以及NTLM的支持。