无法将 WS-Security header 添加到从 Web 引用构建的请求
Unable to add WS-Security header to request built from web reference
我已经使用了 WebReference 并且接收服务器需要 WS-Security header:
<wsse:UsernameToken wsu:Id="Example">
<wsse:Username> ... </wsse:Username>
<wsse:Password Type="..."> ... </wsse:Password>
<wsse:Nonce EncodingType="..."> ... </wsse:Nonce>
<wsu:Created> ... </wsu:Created>
</wsse:UsernameToken>
我原以为这会包含在 WSDL 中,但是在阅读 this post 之后我明白逻辑应该分开。
我用来执行请求的客户端 class 包含一个代理 属性 IWebProxy:HttpWebClientProtocol
。我认为这是我应该提供 header/override 信息的地方。请有人确认一下吗?
我也有一些代码可以生成正确的 headers。但是我不确定如何在不修改 WebReference
.
的情况下指定这些 headers/elements
public static Tuple<EndpointAddress, BindingElementCollection, string, string> PrepareGlowsAuth(string endpoint)
{
EndpointAddress soapEndpoint = new EndpointAddress(string.Format("{0}/{1}", (IsProduction ? productionBaseUrl : testingBaseUrl), endpoint));
BasicHttpsBinding binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
BindingElementCollection elements = binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
return new Tuple<EndpointAddress, BindingElementCollection, string, string>(soapEndpoint, elements, "username", "password");
}
如果有人能指出正确的方向,我将不胜感激!
更新:遵循建议后我看不到客户端或响应 classes.
在不更改客户端 class 的情况下将凭据注入请求的方式如下:
// Assume that you named your "Connected Service" com.example.foo
foo.bar requestObj= new foo.bar();
// Fill in your request object
bar.FirstName = "Someone";
// etc.
// Set up the authentication using the function you provided
var glowsAuthData = PrepareGlowsAuth("expressRateBook");
// foo.<object name>Client is automatically created, this is the generated
// proxy class for communicating with the intended web service
foo.barClient client = new foo.barClient(new CustomBinding(glowsAuthData.Item2)
, glowsAuthData.Item1);
client.ClientCredentials.UserName.UserName = glowsAuthData.Item3;
client.ClientCredentials.UserName.Password = glowsAuthData.Item4;
// Use the client to send the request object and populate the response object
// foo.<object name>Response is automatically generated when VS generates
// the code for "Connected Service". It also makes it the return type
// for foo.barClient.barResponse(foo.bar);
foo.barResponse responseObj = client.barResponse(requestObj);
假设没有异常,responseObj
将包含来自服务器的响应。不需要直接修改使用 WSDL 创建的生成的客户端。
我已经使用了 WebReference 并且接收服务器需要 WS-Security header:
<wsse:UsernameToken wsu:Id="Example">
<wsse:Username> ... </wsse:Username>
<wsse:Password Type="..."> ... </wsse:Password>
<wsse:Nonce EncodingType="..."> ... </wsse:Nonce>
<wsu:Created> ... </wsu:Created>
</wsse:UsernameToken>
我原以为这会包含在 WSDL 中,但是在阅读 this post 之后我明白逻辑应该分开。
我用来执行请求的客户端 class 包含一个代理 属性 IWebProxy:HttpWebClientProtocol
。我认为这是我应该提供 header/override 信息的地方。请有人确认一下吗?
我也有一些代码可以生成正确的 headers。但是我不确定如何在不修改 WebReference
.
public static Tuple<EndpointAddress, BindingElementCollection, string, string> PrepareGlowsAuth(string endpoint)
{
EndpointAddress soapEndpoint = new EndpointAddress(string.Format("{0}/{1}", (IsProduction ? productionBaseUrl : testingBaseUrl), endpoint));
BasicHttpsBinding binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
BindingElementCollection elements = binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
return new Tuple<EndpointAddress, BindingElementCollection, string, string>(soapEndpoint, elements, "username", "password");
}
如果有人能指出正确的方向,我将不胜感激!
更新:遵循建议后我看不到客户端或响应 classes.
在不更改客户端 class 的情况下将凭据注入请求的方式如下:
// Assume that you named your "Connected Service" com.example.foo
foo.bar requestObj= new foo.bar();
// Fill in your request object
bar.FirstName = "Someone";
// etc.
// Set up the authentication using the function you provided
var glowsAuthData = PrepareGlowsAuth("expressRateBook");
// foo.<object name>Client is automatically created, this is the generated
// proxy class for communicating with the intended web service
foo.barClient client = new foo.barClient(new CustomBinding(glowsAuthData.Item2)
, glowsAuthData.Item1);
client.ClientCredentials.UserName.UserName = glowsAuthData.Item3;
client.ClientCredentials.UserName.Password = glowsAuthData.Item4;
// Use the client to send the request object and populate the response object
// foo.<object name>Response is automatically generated when VS generates
// the code for "Connected Service". It also makes it the return type
// for foo.barClient.barResponse(foo.bar);
foo.barResponse responseObj = client.barResponse(requestObj);
假设没有异常,responseObj
将包含来自服务器的响应。不需要直接修改使用 WSDL 创建的生成的客户端。