如何以编程方式更改端点的身份配置?

Posted

技术标签:

【中文标题】如何以编程方式更改端点的身份配置?【英文标题】:How to programmatically change an endpoint's identity configuration? 【发布时间】:2011-11-15 07:39:34 【问题描述】:

我正在尝试创建一个工具来以编程方式修改我的服务的 app.config 文件。代码是这样的,

string _configurationPath = @"D:\MyService.exe.config";
ExeConfigurationFileMap executionFileMap = new ExeConfigurationFileMap();
executionFileMap.ExeConfigFilename = _configurationPath;

System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None);
ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);

foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)

    if (endpoint.Name == "WSHttpBinding_IMyService")
    
        endpoint.Address = new Uri("http://localhost:8080/");
    


config.SaveAs(@"D:\MyService.exe.config");

但是我在更改端点的身份时遇到了问题。

我想要类似的东西:

<identity>
     <userPrincipalName value="user@domain.com" />
</identity>

对于我的端点配置,但是当我尝试时:

endpoint.Identity = new IdentityElement()
    UserPrincipalName = UserPrincipalNameElement()  Value = "user@domain.com" 

它失败是因为属性endpoint.Identity 和identityElement.UserPrincipalName 是只读的(我不知道为什么,因为 entity.Address 不是只读的)

有没有办法绕过这个限制并设置身份配置?

【问题讨论】:

【参考方案1】:

试试这样的...

http://msdn.microsoft.com/en-us/library/bb628618.aspx

    ServiceEndpoint ep = myServiceHost.AddServiceEndpoint(
                typeof(ICalculator),
                new WSHttpBinding(),
                String.Empty);
EndpointAddress myEndpointAdd = new EndpointAddress(new Uri("http://localhost:8088/calc"),
     EndpointIdentity.CreateDnsIdentity("contoso.com"));
ep.Address = myEndpointAdd;

【讨论】:

您好,我正在尝试修改并保存配置文件,而不是尝试修改 ServiceEndpoint 对象【参考方案2】:

我认为框架中没有内置的方法,至少我没有看到任何简单但可能是错误的方法。

我确实看到了另一个问题的答案https://***.com/a/2068075/81251,它使用标准 XML 操作来更改端点地址。这是一个 hack,但它可能会做你想做的事。

为了完整起见,以下是链接答案中的代码:

using System;
using System.Xml;
using System.Configuration;
using System.Reflection;

namespace Glenlough.Generations.SupervisorII

    public class ConfigSettings
    

        private static string NodePath = "//system.serviceModel//client//endpoint";
        private ConfigSettings()  

        public static string GetEndpointAddress()
        
            return ConfigSettings.loadConfigDocument().SelectSingleNode(NodePath).Attributes["address"].Value;
        

        public static void SaveEndpointAddress(string endpointAddress)
        
            // load config document for current assembly
            XmlDocument doc = loadConfigDocument();

            // retrieve appSettings node
            XmlNode node = doc.SelectSingleNode(NodePath);

            if (node == null)
                throw new InvalidOperationException("Error. Could not find endpoint node in config file.");

            try
            
                // select the 'add' element that contains the key
                //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='0']", key));
                node.Attributes["address"].Value = endpointAddress;

                doc.Save(getConfigFilePath());
            
            catch( Exception e )
            
                throw e;
            
        

        public static XmlDocument loadConfigDocument()
        
            XmlDocument doc = null;
            try
            
                doc = new XmlDocument();
                doc.Load(getConfigFilePath());
                return doc;
            
            catch (System.IO.FileNotFoundException e)
            
                throw new Exception("No configuration file found.", e);
            
        

        private static string getConfigFilePath()
        
            return Assembly.GetExecutingAssembly().Location + ".config";
        
    

【讨论】:

【参考方案3】:

对于任何正在寻找解决方案的人,我相信您可以通过以下方式实现它(这是上一个示例的一个小扩展):

    public void ChangeMyEndpointConfig(ChannelEndpointElement existingElement, ServiceModelSectionGroup grp, string identityValue)
    
        EndpointAddress endpointAddress = new EndpointAddress(existingElement.Address, EndpointIdentity.CreateDnsIdentity(identityValue));

        var newElement = new ChannelEndpointElement(endpointAddress, existingElement.Contract)
        
            BehaviorConfiguration = existingElement.BehaviorConfiguration,
            Binding = existingElement.Binding,
            BindingConfiguration = existingElement.BindingConfiguration,
            Name = existingElement.Name
            // Set other values
        ;
        grp.Client.Endpoints.Remove(existingElement);
        grp.Client.Endpoints.Add(newElement);
    

【讨论】:

【参考方案4】:

这被确认为有效。好痛……

public static void ChangeClientEnpoint(string name, Uri newAddress)
    
        System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);
        ChannelEndpointElement existingElement = null;
        foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)
        
            if (endpoint.Name == "BasicHttpBinding_IMembershipService")
            
                existingElement = endpoint;
            
        
        EndpointAddress endpointAddress = new EndpointAddress(newAddress.ToString());
        var newElement = new ChannelEndpointElement(endpointAddress, existingElement.Contract)
        
            BehaviorConfiguration = existingElement.BehaviorConfiguration,
            Binding = existingElement.Binding,
            BindingConfiguration = existingElement.BindingConfiguration,
            Name = existingElement.Name
            // Set other values
        ;
        serviceModeGroup.Client.Endpoints.Remove(existingElement);
        serviceModeGroup.Client.Endpoints.Add(newElement);
        config.Save();
        ConfigurationManager.RefreshSection("system.serviceModel/client");
    

【讨论】:

以上是关于如何以编程方式更改端点的身份配置?的主要内容,如果未能解决你的问题,请参考以下文章

如何配置“健康”执行器端点以使用令牌身份验证?

以编程方式使用证书身份验证配置 WCF 服务客户端

使用 Spring Security 4 以编程方式对用户进行身份验证

作为管理员,如何使用 Grails Spring Security 以编程方式更改用户密码?

如何以编程方式修改 WCF app.config 端点地址设置?

React Native:登录或注销时如何以编程方式刷新应用程序?