我是一个ASP.NET MVC应用程序,我们使用多个外部服务。
我们以这种方式为web.config中的每个服务定义端点:
<endpoint address="http://tempuri.org/myExternalServiceEndPointAddress"
binding="basicHttpBinding" bindingConfiguration="myExternalServiceBinding" contract="myExternalServiceContract" name="MyExternalServiceName">
<headers>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>myUsername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
现在,当切换到生产环境时,我们必须通过特定服务发现实际的端点URL,因为它们可以在没有警告的情况下进行更改。找到新端点后,我们在执行任何方法调用之前更改端点URL:
myserviceClientObject.Endpoint.Address = new EndpointAddress(newEndpointUrl);
完成此操作后,方法调用在newEndpointUrl中正确处理,但调用已丢失包含验证的标头节点。
我们尝试通过
以编程方式添加身份验证myServiceClientObject.ClientCredentials.Username.Username = myUsername;
myServiceClientObject.ClientCredentials.Username.Password = myPassword;
但是,该服务似乎无法识别此身份验证(而前一个身份验证工作正常,直到我们更改了端点)。
非常感谢任何见解或建议。
答案 0 :(得分:0)
我终于解决了这个问题。
我们最终做的是将带有所需标题的对象连接到WCF管道。
为此,我们创建了一个在服务中添加客户端行为的类,以及另一个定义了注入的行为本身的类。
以下是代码:
添加行为的类
public class EndpointAddCredentials : IEndpointBehavior {
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new SimpleMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
}
在发送请求之前定义和应用它的类
public class SimpleMessageInspector : IClientMessageInspector, IDispatchMessageInspector {
public void AfterReceiveReply(ref Message reply, object correlationState) {
}
public object BeforeSendRequest(ref Message request, IClientChannel channel) {
UsernameToken authentication = new UsernameToken(remoteServiceUsername, remoteServicePassword, PasswordOption.SendPlainText); //Plain text is server requirement, we cannot do anything
var webUserHeader = MessageHeader.CreateHeader("Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", authentication.GetXml(new XmlDocument()));
request.Headers.Add(webUserHeader);
return null;
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) {
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) {
}
}
然后,在服务重定向之后,我们只需要将行为添加到客户端对象
serviceObject.Endpoint.Behaviors.Add(new EndpointAddCredentials());
有了这个,对服务器的请求包括我们正在寻找的安全定义,服务器接受了它们。