【发布时间】:2012-02-21 06:22:57
【问题描述】:
这可能很愚蠢/不可能。但是,我想要实现的目标如下:
- 我有一个在 Windows Server 2008 上的 IIS 7 中托管 WCF Web 服务的 VM
- 我正在使用基本的http绑定
- 客户端代码在其他机器上完美运行
- 此服务器虚拟机还需要执行批处理,因此我需要在其上使用客户端访问这些 WCF 服务
-
在托管 WCF 服务的实际机器上运行时,我得到...
System.ServiceModel.Security.MessageSecurityException:HTTP 请求未经客户端身份验证方案“Ntlm”授权。从服务器收到的身份验证标头是“协商,NTLM”。 ---> System.Net.WebException:远程服务器返回错误:(401)未经授权。 在 System.Net.HttpWebRequest.GetResponse() 在 System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(时间跨度超时) --- 内部异常堆栈跟踪结束 ---
服务器堆栈跟踪: 在 System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest 请求,HttpWebResponse 响应,WebException responseException,HttpChannelFactory 工厂) 在 System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest 请求,HttpWebResponse 响应,HttpChannelFactory 工厂,WebException responseException) 在 System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(时间跨度超时) 在 System.ServiceModel.Channels.RequestChannel.Request(消息消息,TimeSpan 超时) 在 System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息消息,TimeSpan 超时) 在 System.ServiceModel.Channels.ServiceChannel.Call(字符串操作,布尔单向,ProxyOperationRuntime 操作,Object[] 输入,Object[] 输出,TimeSpan 超时) 在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime 操作) 在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息)
在 [0] 处重新抛出异常: 在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg) 在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 类型)
我想知道的是我正在尝试的事情是否真的可行 - 我看不出为什么我不能从主机连接到服务,但具体情况可能会阻止我 - 如果是的话,什么我需要对我的设置进行更改才能实现它?
相关dll设置绑定如下...
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.TransferMode = TransferMode.Buffered;
binding.MaxBufferPoolSize = int.MaxValue;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.OpenTimeout = openTimeout;
binding.SendTimeout = sendTimeout;
binding.ReceiveTimeout = receiveTimeout;
binding.CloseTimeout = closeTimeout;
return binding;
cscript 认证的输出是...
NTAuthenticationProviders : (STRING) "Negotiate,NTLM"
该服务设置为要求连接用户所属的网络组的成员身份 (PrincipalPermission)。
如下 cmets 所示,我查看了安全事件日志,发现当用户(网络帐户)作为客户端连接到主机上的 WCF 服务时,有一个条目抱怨该帐户无法登录- 传递了一个空 SID。
An account failed to log on.
Subject:
Security ID: NULL SID
Account Name: -
Account Domain: -
Logon ID: 0x0
Logon Type: 3
Account For Which Logon Failed:
Security ID: NULL SID
Account Name: *<network account>*
Account Domain: *<account domain>*
Failure Information:
Failure Reason: An Error occured during Logon.
Status: 0xc000006d
Sub Status: 0x0
问题是,为什么会这样?
【问题讨论】:
-
客户端没有配置 - 它是一个 DLL - 所以设置是以编程方式执行的。 binding.Security.Transport.ClientCredentialType 行对 NTLM 执行设置。我相信这个问题是由于我在托管服务的服务器上运行客户端代码,因为这在其他地方工作。我只是不知道要改变什么。
-
我还尝试将客户端更改为使用 Windows 而不是 NTLM。获得类似的回击,但在错误消息中将 Ntlm 与 Negotiate 交换。我确定这是一个“仅在服务器上”的问题,可能是 WCF,可能是 IIS 配置等。
-
我现在已经查看了相关服务器上的安全事件日志,当 WCF 服务作为服务主机上的客户端连接时,它似乎正在接收该帐户的 Null SID。问题是,为什么 SID 为空?
标签: c# wcf authentication ntlm