简体   繁体   English

以编程方式更改WCF服务端点后,维护安全配置

[英]Maintain security configuration after changing WCF service endpoint programmatically

I've an ASP.NET MVC application where we use several external services. 我有一个ASP.NET MVC应用程序,我们使用几个外部服务。

We define the endpoint to each of the services in web.config in this fashion: 我们以这种方式为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>

Now, when switching to production environment, we had to discover the actual endpoint url through a specific service, as they can change without warning. 现在,当切换到生产环境时,我们必须通过特定服务发现实际的端点URL,因为它们可以在没有警告的情况下进行更改。 Once the new endpoint is found, we change the endpoint url before executing any method call with this: 一旦找到新的端点,我们将在执行任何方法调用之前更改端点URL:

myserviceClientObject.Endpoint.Address = new EndpointAddress(newEndpointUrl);

Once we make this, the method call is correctly addressed at newEndpointUrl, but the call has lost header nodes where validation is included. 完成此操作后,方法调用在newEndpointUrl中正确处理,但调用已丢失包含验证的标头节点。

We've tried to add authentication programatically through 我们试图以编程方式添加身份验证

myServiceClientObject.ClientCredentials.Username.Username = myUsername;
myServiceClientObject.ClientCredentials.Username.Password = myPassword;

However, the service doesn't seems to recognize this authentication (while previous one was working perfectly until we changed the endpoint). 但是,该服务似乎无法识别此身份验证(在我们更改端点之前,上一个身份验证正常运行)。

Any insight or suggestion will be much appreciated. 任何见解或建议将不胜感激。

I've finally solved this problem. 我终于解决了这个问题。

What we did in the end was to wire into the WCF pipeline an object with the desired headers. 我们最终做的是将具有所需标头的对象连接到WCF管道。

To do this we create a class that added a client behavior in the service and another one which defined the behavior itself, where the injection was made. 为此,我们创建了一个类,该类在服务中添加了一个客户端行为,另一个类定义了行为本身,即进行注入的位置。

Here is the code: 这是代码:

Class that adds the behavior 添加行为的类

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) { }

}

Class that defines and applies it before sending requests 在发送请求之前定义和应用它的类

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) {
    }
}

Then, after service redirection, we just have to add the behavior to our client object 然后,在服务重定向之后,我们只需要将行为添加到我们的客户端对象中

serviceObject.Endpoint.Behaviors.Add(new EndpointAddCredentials()); 

With this the requests to the server included the security definition we were looking for and the server accepted them. 有了这个,对服务器的请求包括我们正在寻找的安全定义,服务器接受了它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM