在运行时替换web.config appsettings中的值(用于Active Directory身份验证)

本文关键字:用于 Active Directory 身份验证 替换 运行时 web config appsettings | 更新日期: 2023-09-27 18:20:34

一些背景。。。

我已经使用ConfigurationManager看到了答案,但我认为我试图实现的略有不同。

我正在将MVC5部署为Azure云服务。客户想要一个测试/用户接受/直播的单一交付包,其中所有(如果可能)设置都存储在Azure配置设置中。对于我们自己的appSettings值,这不是问题,请将它们移动到ServiceConfiguration.cscfg,并通过调用CloudConfigurationManager.GetSetting读取它们(如果部署在Azure角色中,则从Azure cscfg读取,如果在开发期间在IIS中本地运行,则从web.config读取)

然而,Microsoft.Web.RedisSessionStateProvider仍然存在问题,支持从Web.config读取设置(我给开发人员发了电子邮件,他们确认了这一点)

我通过从Azure上的ServiceConfiguration.cscfg中读取连接字符串并将其填充到内存中的web.config中来解决这个问题,如下所示,这似乎是允许MVC自己配置会话处理的可行方法。

        private void UpdateConfigurationSettings()
    {
        // Obtain the RuntimeConfig type.
        var runtimeConfig = Type.GetType("System.Web.Configuration.RuntimeConfig, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
        // Obtain the RuntimeConfig instance.
        var runtimeConfigInstance = runtimeConfig.GetMethod("GetAppConfig", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
        UpdateRedisSessionStateSettings(runtimeConfig, runtimeConfigInstance);
        UpdateAppSettings(runtimeConfig, runtimeConfigInstance);
    }
    private static void UpdateRedisSessionStateSettings(Type runtimeConfig, object runtimeConfigInstance)
    {
        // Obtain the SessionStateSection instance.
        SessionStateSection sessionStateSection =
            (SessionStateSection)
                runtimeConfig.GetProperty("SessionState", BindingFlags.NonPublic | BindingFlags.Instance)
                    .GetValue(runtimeConfigInstance, null);
        // Since the SessionStateSection is set to read only be dafault, we must make it writeable.
        typeof (ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(sessionStateSection, false);

        // Get the provider from the SessionStateSection
        var provider = sessionStateSection.Providers[0];
        // Since the provider is set to read only be dafault, we must make it writeable.
        typeof (ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(provider, false);
        // Update the connection string paramter of the provider
        provider.Parameters.Set("connectionString", ConfigurationParameters.RedisCacheConnectionString);
        // Just read it back - this is only for debugging so I can see that the value has been updated.
        var c = provider.Parameters["connectionString"];
    }

问题是Active Directory

我现在真正的问题是Azure Active Directory设置,我希望做类似的事情,但我似乎无法使用相同的方法访问appSettings部分。尝试按如下方式读取appSettings会得到一个空指针,事实上,如果您调试到runtimeConfigInstance中,则其他部分都可用,但appSettings不可用!

        private void UpdateAppSettings(Type runtimeConfig, object runtimeConfigInstance)
    {
        // Obtain the AppSettings section instance.
        AppSettingsSection appSettingsSection =
            (AppSettingsSection)
                runtimeConfig.GetProperty("appSettings", BindingFlags.NonPublic | BindingFlags.Instance)
                    .GetValue(runtimeConfigInstance, null);
        // Since the AppSettings section is set to read only be dafault, we must make it writeable.
        typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(appSettingsSection, false);

    }

所以我的问题有两个方面:

  1. 是否可以在不使用ConfigurationManager和保存文件的情况下以相同的方式访问appSettings?

  2. 有没有其他方法可以从Azure设置而不是在web.config中读取Active Directory定义,从而为我们提供一个可交付的单个包,其中所有设置都可以在Azure上配置?

注意:我使用以下操作从cscfg读取值的FederationConfiguration,但web.config中的appSettings键ida:FederationMetadataLocation ida:Realm ida:AudienceUri也需要正确。。

        private void FederatedAuthenticationOnFederationConfigurationCreated(object sender, FederationConfigurationCreatedEventArgs args)
    {
        args.FederationConfiguration.IdentityConfiguration.AudienceRestriction.AllowedAudienceUris[0] = new Uri(ConfigurationParameters.ActiveDirectoryAudienceUri);
        args.FederationConfiguration.WsFederationConfiguration.Issuer = ConfigurationParameters.ActiveDirectoryIssuer;
        args.FederationConfiguration.WsFederationConfiguration.Realm = ConfigurationParameters.ActiveDirectoryRealm;
    }

在运行时替换web.config appsettings中的值(用于Active Directory身份验证)

以下是您的解决方案。

步骤1:编写有关如何读取连接字符串的自定义代码。在这个例子中,我首先阅读了云配置,然后返回到web配置。

using System;
using System.Configuration;
using Microsoft.Azure;
namespace Namespace1 {
    public class RedisConnectionStringProvider {
        public static string GetConnectionString() {
            const string redisConnectionString="redisConnectionString";
            var cloudConfigurationValue = CloudConfigurationManager.GetSetting(redisConnectionString);
            if (!String.IsNullOrEmpty(cloudConfigurationValue))
                return cloudConfigurationValue;
            var connectionStringSettings = ConfigurationManager.ConnectionStrings[redisConnectionString];
            if (connectionStringSettings == null) {
                throw new ConfigurationErrorsException("A connection string is expected for " + redisConnectionString);
            }
            return connectionStringSettings.ConnectionString;
        }

步骤2.现在,告诉提供者调用连接字符串的自定义实现。

<sessionState mode="Custom" timeout="60" customProvider="RedisSessionProvider">
      <providers>
        <add name="RedisSessionProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" settingsClassName="Namespace1.RedisConnectionStringProvider, AssemblyName, Culture=neutral" settingsMethodName="GetConnectionString"/>
      </providers>
</sessionState>