我们遇到了这个问题,发现当使用(在我们的例子中是 IE)浏览器作为进程帐户登录时,然后通过应用程序(SharePoint)更改会话登录时会引发错误。我相信这种情况通过了两种身份验证方案:
- 谈判
- NTLM
该应用程序托管了一个 *.asmx Web 服务,该服务在负载平衡服务器上被调用,并使用类似 WCF 的 .NET3.5 绑定向自身发起 Web 服务调用。
用于调用 Web 服务的代码:
public class WebServiceClient<T> : IDisposable
{
private readonly T _channel;
private readonly IClientChannel _clientChannel;
public WebServiceClient(string url)
: this(url, null)
{
}
/// <summary>
/// Use action to change some of the connection properties before creating the channel
/// </summary>
public WebServiceClient(string url,
Action<CustomBinding, HttpTransportBindingElement, EndpointAddress, ChannelFactory> init)
{
var binding = new CustomBinding();
binding.Elements.Add(
new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8));
var transport = url.StartsWith("https", StringComparison.InvariantCultureIgnoreCase)
? new HttpsTransportBindingElement()
: new HttpTransportBindingElement();
transport.AuthenticationScheme = System.Net.AuthenticationSchemes.Ntlm;
binding.Elements.Add(transport);
var address = new EndpointAddress(url);
var factory = new ChannelFactory<T>(binding, address);
factory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
if (init != null)
{
init(binding, transport, address, factory);
}
this._clientChannel = (IClientChannel)factory.CreateChannel();
this._channel = (T)this._clientChannel;
}
/// <summary>
/// Use this property to call service methods
/// </summary>
public T Channel
{
get { return this._channel; }
}
/// <summary>
/// Use this porperty when working with
/// Session or Cookies
/// </summary>
public IClientChannel ClientChannel
{
get { return this._clientChannel; }
}
public void Dispose()
{
this._clientChannel.Dispose();
}
}
我们发现,如果会话凭据与浏览器的进程帐户相同,则仅使用 NTLM 并且调用成功。否则会导致这个捕获的异常:
HTTP 请求未经客户端身份验证方案“Ntlm”授权。从服务器收到的身份验证标头是“协商,NTLM”。
最后,我相当肯定其中一个身份验证方案会通过身份验证,而另一个不会,因为它没有被授予适当的访问权限。