防止后续服务调用的协商握手
Preventing negotiation handshake on subsequent service calls
我正在调用一个使用 Windows 身份验证的 SOAP 服务。这是我的配置:
new BasicHttpBinding
{
Security = new BasicHttpSecurity
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Windows
}
},
};
我在这里手动设置凭据,因为用户在不同的域中:
client.ClientCredentials.Windows.ClientCredential.Domain = "...";
client.ClientCredentials.Windows.ClientCredential.UserName = "...";
client.ClientCredentials.Windows.ClientCredential.Password = "...";
我注意到我通过客户端代理进行的每次调用都会产生三个行程:
Request: POST /EndPoint (no auth)
Response: 401 Unauthorized, WWW-Authenticate: Negotiate
Request: POST /EndPoint, Authorization: Negotiate
Response: 401 Unauthorized, WWW-Authenticate: Negotiate <gunk>
Request: Post /EndPoint, Authorization: Negotiate <gunk>
Response: 200 OK
如果这只发生在第一次调用时就不会那么糟糕,但它会发生在对同一客户端代理实例的所有后续调用中。
我呼叫的服务器不在我的控制之下,并且有相当多的延迟,所以我很想找到一种方法来消除这些多余的行程。可能吗?
我刚刚使用您的绑定设置和手动 un+pwd 身份验证创建了带有 WCF 服务的虚拟客户端。 WCF 服务设置为接受 Windows 身份验证。
但是,在我的例子中,所有后续调用都会自动进行身份验证。
Request: Post /Service1.svc
回复 1:
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
回复 2:
HTTP/1.1 401 Unauthorized
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate xxxxxxxxxxxxxxxxxxxxxxxxxx.....
回复 3:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 202
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate xxxxxxx....
在响应 header 中,我有 Persistent-Auth: true
。这对你来说是一样的吗?如果不是 - IIS 中有一些设置可以强制客户端在每次请求后进行身份验证 - 请参阅此 MSDN post。
基本上,我想你必须在服务器上:
authPersistSingleRequest = False
authPersistNonNTLM = True
然后就可以了。
我正在调用一个使用 Windows 身份验证的 SOAP 服务。这是我的配置:
new BasicHttpBinding
{
Security = new BasicHttpSecurity
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Windows
}
},
};
我在这里手动设置凭据,因为用户在不同的域中:
client.ClientCredentials.Windows.ClientCredential.Domain = "...";
client.ClientCredentials.Windows.ClientCredential.UserName = "...";
client.ClientCredentials.Windows.ClientCredential.Password = "...";
我注意到我通过客户端代理进行的每次调用都会产生三个行程:
Request: POST /EndPoint (no auth)
Response: 401 Unauthorized, WWW-Authenticate: Negotiate
Request: POST /EndPoint, Authorization: Negotiate
Response: 401 Unauthorized, WWW-Authenticate: Negotiate <gunk>
Request: Post /EndPoint, Authorization: Negotiate <gunk>
Response: 200 OK
如果这只发生在第一次调用时就不会那么糟糕,但它会发生在对同一客户端代理实例的所有后续调用中。
我呼叫的服务器不在我的控制之下,并且有相当多的延迟,所以我很想找到一种方法来消除这些多余的行程。可能吗?
我刚刚使用您的绑定设置和手动 un+pwd 身份验证创建了带有 WCF 服务的虚拟客户端。 WCF 服务设置为接受 Windows 身份验证。
但是,在我的例子中,所有后续调用都会自动进行身份验证。
Request: Post /Service1.svc
回复 1:
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
回复 2:
HTTP/1.1 401 Unauthorized
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate xxxxxxxxxxxxxxxxxxxxxxxxxx.....
回复 3:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 202
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate xxxxxxx....
在响应 header 中,我有 Persistent-Auth: true
。这对你来说是一样的吗?如果不是 - IIS 中有一些设置可以强制客户端在每次请求后进行身份验证 - 请参阅此 MSDN post。
基本上,我想你必须在服务器上:
authPersistSingleRequest = False
authPersistNonNTLM = True
然后就可以了。