• 30
  • 十一月

PHP 使用 cURL 函数验证 NTLM

Kenami 发布于 11:18:50  |  阅读 268 次 |  1 条评论  

最近同事做了一个手机接口,对方的短信业务接口平台是.net,并使用NTLM登录,因为以前都没有做过此类的接口,所以,我也来帮着找找解决方法。
先看看什么是NTLM

NTLM是NT LAN Manager的缩写,这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议,Windows 2000 支持 NTLM 是为了保持向后兼容。Windows 2000内置三种基本安全协议之一

用php如何在页面程序里面登录NTLM呢?网上说了要用到cURL,自己在查了一下,获得了以下的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$param = "bstrMoMessageID=12231707088395410640" .
		"&bstrBusinessCode=4668" .
		"&bstrLongCode=3" .
		"&bstrFeeMsisdn=15800394478" .
		"&bstrDesMsisdn=15800394478" .
		"&bstrMessageContent=你好" .
		"&lTpPid=0" .
		"&lTpUdhi=0" .
		"&lSendDate=20091127" .
		"&lSendTime=122320" .
		"&lExpireDate=20091" .
		"&lExpireTime=122320";
 
$path = "http://*****/SmbpHttpAgent/SmbpHttpAgent.asmx/SmbppSendUnicodeMessage";
$user = "4668";
$password = "******";
$action = "http://*****.com/SmbpHttpAgent/SmbppSendASCIIMessage";
$headers = array(
			'Method: POST',
			'Connection: Keep-Alive',
			'User-Agent: PHP-SOAP-CURL',
			'Content-Type: application/x-www-form-urlencoded',
			'SOAPAction: "'.$action.'"',//对应说明文档的action
		);
$ch = curl_init($path);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);//post 的参数
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
echo $buffer = curl_exec($ch);

另外附上.net实现NTLM的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//向短信业务平台提交数据
private int SendDataToWapdm(string destURL,string paramStr)
{
	int Result = 0;
	WebResponse response = null;
	try 
	{				
		//短信业务平台为商户提供的连接ID
		string username = "4648";
		//短信业务平台为商户提供的连接密码
		string password = "******";
		//为基于密码的身份验证方案提供凭据
		System.Net.NetworkCredential credentials = new NetworkCredential(username,password);	
		//提供向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法
		System.Net.WebClient Client = new System.Net.WebClient();
		//存储 Internet 资源的凭据
		System.Net.CredentialCache myCache = new System.Net.CredentialCache();
		//向凭据缓存添加 NetworkCredential 实例
		myCache.Add(new Uri(destURL), "NTLM", credentials);
 
		WebRequest req = WebRequest.Create(destURL);
		req.Credentials = myCache;
		//使用post方式传递参数
		req.Method = "POST";
		req.ContentType = "application/x-www-form-urlencoded";
		StringBuilder UrlEncoded = new StringBuilder();
		Char[] reserved = {'?', '=', '&'};
		byte[] SomeBytes = null;
		//分析传递给短信业务平台的参数并写入到Stream中
		if (paramStr != null) 
		{
			int i=0, j;
			while(i<paramStr.Length)
			{
				j=paramStr.IndexOfAny(reserved, i);
				if (j==-1)
				{
					UrlEncoded.Append(HttpUtility.UrlEncode(paramStr.Substring(i, paramStr.Length-i)));
					break;
				}
				UrlEncoded.Append(HttpUtility.UrlEncodeUnicode(paramStr.Substring(i, j-i)));//这个地方需要UrlEncodeUnicode
				string s = UrlEncoded.ToString();
				UrlEncoded.Append(paramStr.Substring(j,1));
				i = j+1;
			}
			SomeBytes = Encoding.UTF8.GetBytes(UrlEncoded.ToString());
			req.ContentLength = SomeBytes.Length;
			Stream newStream = req.GetRequestStream();
			newStream.Write(SomeBytes, 0, SomeBytes.Length);
			newStream.Close();
		} 
		else 
		{
			req.ContentLength = 0;
		}
 
		//获取短信业务平台的response
		response = req.GetResponse();
		//获取response数据流
		Stream ReceiveStream = response.GetResponseStream();
		Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
		StreamReader sr = new StreamReader( ReceiveStream, encode );
		//Console.WriteLine("\r\n已接收到响应流");
		Char[] read = new Char[256];
		int count = sr.Read( read, 0, 256 );
		StringBuilder buf = new StringBuilder();
		while (count > 0) 
		{
			String str = new String(read, 0, count);
			buf.Append(str);
			count = sr.Read(read, 0, 256);
		}
		buf.Replace("\r\n","");//不知道为什么用C#处理的流中含有\r\n(在java中没有这种情况的)
		//在这个地方调用分析短信业务平台发送消息后的回应的方法
		Result = this.parseWAPDMResponse(buf.ToString());
 
	} 
	catch(UriFormatException ex) 
	{
		Result = CONNECT_ERROR;
		Console.WriteLine( ex.ToString());
		//Page.Response.Write(e.StackTrace);
		//Page.Response.Write(e.Message);
		Console.WriteLine("\r\n找不到请求 URI,或者它的格式不正确");
	} 
	catch(IOException ex)
	{
		Result = IO_ERROR;
		Console.WriteLine(ex.ToString());
	}
	finally 
	{
		if ( response != null ) 
		{
			response.Close();
		}
	}
	return Result;
}

评论

1 条评论

  • 1楼  玉米价格   发表于: 十二月 6, 2009   12:46 上午

    朋友,来踩踩你的博客来了,记得回踩哦。我的玉米价格够酷的.

    [回复]