C#和php中的NTLM请求


NTLM request in C# and php

我在C#中有一个ntlm请求,它可以工作,在php中有相同的请求,它连接,但在响应中返回错误。

这是c#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://example.com/Query/ExecuteReportView");
            httpWebRequest.ContentType = "text/json";
            httpWebRequest.Method = "POST";
            httpWebRequest.UseDefaultCredentials = false;
            httpWebRequest.PreAuthenticate = true;
            var c = new NetworkCredential("username", "password", "domain");
            CredentialCache credentialCache = new CredentialCache();
            credentialCache.Add(new Uri("http://example.com"), "NTLM", c);
            httpWebRequest.Credentials = credentialCache;
            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                string json = "{'"SysName'":'"Callbacks'"," +
                                "'"SysCategory'":'"Eai.CCM.Model.FolderView'"," +
                                "'"StartIndex'":0," +
                                "'"PageLength'":10}";

                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            }
            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                var result = streamReader.ReadToEnd();
                Console.Out.WriteLine(result);
            }
            Console.ReadLine();
        }
    }
}

这很有效,并按预期返回一个json字符串。

以下是我在php:中做的同样的尝试

<?php
$data = array
(
  "SysName" => "Callbacks",
  "SysCategory" => "Eai.CCM.Model.FolderView",
  "StartIndex" => 0,
  "PageLength" => 10
);
$body = json_encode($data);
$headers = array(
    "Transfer-Encoding: chunked",
    "Content-Type: application/json"
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, 'username:password');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, 'example.com/Query/ExecuteReportView');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_FAILONERROR, 0);
curl_setopt($ch, CURLOPT_MAXREDIRS, 100);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, dechex(strlen($body)) . "'r'n" . $body . "'r'n");
curl_exec($ch);
curl_close($ch);
?>

一个显著的区别是,php代码使用分块编码,因为内容长度方法一直给我一个错误,告诉我需要指定内容长度或发送分块的数据。

对于我在php脚本中遗漏的人来说,有什么明显的突出之处吗?

php脚本连接并返回一个响应,所以我显然没有给它正确的信息(就像我在c#版本中一样)。

这是php版本返回的内容:

{"$id":"1","Message":"An error has occurred.","ExceptionMessage":"Object reference not set to an instance of an object.","ExceptionType":"System.Exception","StackTrace":null}

我使用的是php 5.6.6。

编辑:

我的php脚本在php 5.2.17中使用内容长度而不是分块编码数据

php 5.5.21 中存在相同问题

phpinfo为5.2.17提供了以下内容:

cURL support        enabled
cURL Information    libcurl/7.21.0 OpenSSL/0.9.8q zlib/1.2.3

5.6.6 如下

cURL support     enabled
cURL Information 7.40.0
Age              3
Features
AsynchDNS       Yes
CharConv        No
Debug           No
GSS-Negotiate   No
IDN             Yes
IPv6            Yes
krb4            No
Largefile       Yes
libz            Yes
NTLM            Yes
NTLMWB          No
SPNEGO          Yes
SSL             Yes
SSPI            Yes
TLS-SRP         No
Protocols       dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp
Host            i386-pc-win32
SSL Version     OpenSSL/1.0.1k
ZLib Version    1.2.7.3
libSSH Version  libssh2/1.4.3

终于得到了答案:

似乎IIS正在为我做一些事情。似乎发送头"Transfer-Encoding:chunked"告诉IIS为我做分块。所以我不需要自己对数据进行分块。

<?php
$data = array
(
  "SysName" => "Callbacks",
  "SysCategory" => "Eai.CCM.Model.FolderView",
  "StartIndex" => 0,
  "PageLength" => 10
);
$body = json_encode($data);
$headers = array(
    "Transfer-Encoding: chunked",
    'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, 'username:password');
curl_setopt($ch, CURLOPT_URL, 'example.com/Query/ExecuteReportView');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_exec($ch);
curl_close($ch);
?>