Как развернуть веб-приложение asp.net в команде разработчиков через TFS при настройке аутентификации ADFS - PullRequest
2 голосов
/ 13 декабря 2011

Я работаю над веб-приложением asp.net, которое является частью TFS и используется командой разработчиков.Недавно в рамках проекта мы настроили ADFS и сейчас пытаемся обеспечить аутентификацию проекта на сервере ADFS.

На моей машине для разработки я прошел этапы добавления ссылки на STS, которая генерирует метаданные федерации, а также обновляет файл web.config для проекта.Авторизация в web.config использует сертификацию отпечатка пальца, которая требует от меня добавить на локальный компьютер сертификат ADFS, а также сгенерировать подписанный сертификат для компьютера разработчика и добавить его в ADFS.

Все настроено и работает, но при просмотре web.config.и FederationMetadata.xml документ, который "кажется", чтобы быть определенным для машины.Я подозреваю, что если я проверю проект / файлы в TFS, то следующий разработчик или тестировщик, который берет сборку, в итоге получит сломанную сборку на своем компьютере.

Мой вопрос в TFS, каков процесс для сценария, подобного этому, чтобы зарегистрироваться и все еще позволить моей команде проверять, создавать и тестировать проект с последним кодом в своих средах разработки или тестирования?

В настоящее время моя работа заключается в том, чтобы исключить проверку FederationMetaData.xml и web.config из проверки, а затем на каждом компьютере разработки вручную настроить проверку подлинности ADFS, а также для тестирования продукта.После этого каждый пользователь может запретить проверку своих локальных копий FederationMetatData.xml и web.config.проверьте их в TFS)

Это кажется крайне неэффективным, и почти обходит суть управления исходным кодом, поскольку разработчики обязаны хранить локальные копии файлов на своем компьютере.Похоже, что это также дает возможность случайной регистрации локальных файлов или перезаписи локальных файлов.

Есть ли у кого-нибудь какие-либо ссылки, документация или информация о том, как зарегистрировать код для (ADFS) конкретных конфигураций машины, а не объединить всю среду разработки?

Заранее спасибо,

1 Ответ

6 голосов
/ 01 января 2012

Я согласен с тем, что способ настройки WIF-инструментария не подходит для работы в командах с несколькими разработчиками и тестовыми средами. Подход, который я использовал, чтобы обойти это, заключается в изменении WIF для настройки во время выполнения.

Один из подходов, который вы можете использовать, - это установить на место манекен /FederationMetadata/2007-06/FederationMetadata.xml и проверить его в TFS. Он должен иметь действительные URL-адреса и быть действительным файлом.

Кроме того, вам понадобится действительный раздел federationAuthentication в web.config с фиктивной (но действительной формы) audienceUris, issuer и realm записями.

  <microsoft.identityModel>
    <service>
      <audienceUris>
        <add value="https://yourwebsite.com/" />
      </audienceUris>
      <federatedAuthentication>
        <wsFederation passiveRedirectEnabled="true" issuer="https://yourissuer/v2/wsfederation" realm="https://yourwebsite.com/" requireHttps="true" />
        <cookieHandler requireSsl="false" />
      </federatedAuthentication>
      etc...

Затем измените конфигурацию ADFS вашего приложения, чтобы она была полностью управляемой во время выполнения . Это можно сделать, подключившись к различным событиям во время запуска модуля ADFS и конвейера ASP.NET.

Посмотрите это сообщение на форуме для получения дополнительной информации.

По сути, вам нужно что-то подобное в global.asax.cs. Это некоторый код, который я использовал для веб-роли Windows Azure для чтения из ServiceConfiguration.cscfg (который можно изменить во время развертывания / выполнения в модели Azure). Его можно легко адаптировать для чтения из web.config или любой другой системы конфигурации по вашему выбору (например, базы данных).

    protected void Application_Start(object sender, EventArgs e)
    {
        FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;
    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        /// Due to the way the ASP.Net pipeline works, the only way to change 
        /// configurations inside federatedAuthentication (which are configurations on the http modules)
        /// is to catch another event, which is raised everytime a request comes in.
        ConfigureWSFederation();
    }

    /// <summary>
    /// Dynamically load WIF configuration so that it can live in ServiceConfiguration.cscfg instead of Web.config
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="eventArgs"></param>
    void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs eventArgs)
    {
        try
        {
            ServiceConfiguration serviceConfiguration = eventArgs.ServiceConfiguration;

            if (!String.IsNullOrEmpty(RoleEnvironment.GetConfigurationSettingValue("FedAuthAudienceUri")))
            {
                serviceConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(RoleEnvironment.GetConfigurationSettingValue("FedAuthAudienceUri")));
                Trace.TraceInformation("ServiceConfiguration: AllowedAudienceUris = {0}", serviceConfiguration.AudienceRestriction.AllowedAudienceUris[0]);
            }

            serviceConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
            Trace.TraceInformation("ServiceConfiguration: CertificateValidationMode = {0}", serviceConfiguration.CertificateValidationMode);

            // Now load the trusted issuers
            if (serviceConfiguration.IssuerNameRegistry is ConfigurationBasedIssuerNameRegistry)
            {
                ConfigurationBasedIssuerNameRegistry issuerNameRegistry = serviceConfiguration.IssuerNameRegistry as ConfigurationBasedIssuerNameRegistry;

                // Can have more than one. We don't.
                issuerNameRegistry.AddTrustedIssuer(RoleEnvironment.GetConfigurationSettingValue("FedAuthTrustedIssuerThumbprint"), RoleEnvironment.GetConfigurationSettingValue("FedAuthTrustedIssuerName"));
                Trace.TraceInformation("ServiceConfiguration: TrustedIssuer = {0} : {1}", RoleEnvironment.GetConfigurationSettingValue("FedAuthTrustedIssuerThumbprint"), RoleEnvironment.GetConfigurationSettingValue("FedAuthTrustedIssuerName"));
            }
            else
            {
                Trace.TraceInformation("Custom IssuerNameReistry type configured, ignoring internal settings");
            }

            // Configures WIF to use the RsaEncryptionCookieTransform if ServiceCertificateThumbprint is specified.
            // This is only necessary on Windows Azure because DPAPI is not available.
            ConfigureWifToUseRsaEncryption(serviceConfiguration);
        }
        catch (Exception exception)
        {
            Trace.TraceError("Unable to initialize the federated authentication configuration. {0}", exception.Message);
        }
    }

    /// <summary>
    /// Configures WIF to use the RsaEncryptionCookieTransform, DPAPI is not available on Windows Azure.
    /// </summary>
    /// <param name="requestContext"></param>
    private void ConfigureWifToUseRsaEncryption(ServiceConfiguration serviceConfiguration)
    {
        String svcCertThumbprint = RoleEnvironment.GetConfigurationSettingValue("FedAuthServiceCertificateThumbprint");

        if (!String.IsNullOrEmpty(svcCertThumbprint))
        {
            X509Store certificateStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            try
            {
                certificateStore.Open(OpenFlags.ReadOnly);
                // We have to pass false as last parameter to find self-signed certs.
                X509Certificate2Collection certs = certificateStore.Certificates.Find(X509FindType.FindByThumbprint, svcCertThumbprint, false /*validOnly*/);

                if (certs.Count != 0)
                {
                    serviceConfiguration.ServiceCertificate = certs[0];
                    // Use the service certificate to protect the cookies that are sent to the client.
                    List<CookieTransform> sessionTransforms =
                        new List<CookieTransform>(new CookieTransform[] { new DeflateCookieTransform(),
                                new RsaEncryptionCookieTransform(serviceConfiguration.ServiceCertificate)});

                    SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

                    serviceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
                    Trace.TraceInformation("ConfigureWifToUseRsaEncryption: Using RsaEncryptionCookieTransform for cookieTransform");
                }
                else
                {
                    Trace.TraceError("Could not find service certificate in the My store on LocalMachine");
                }
            }
            finally
            {
                certificateStore.Close();
            }
        }
    }

    private static void ConfigureWSFederation()
    {
        // Load the federatedAuthentication settings
        WSFederationAuthenticationModule federatedModule = FederatedAuthentication.WSFederationAuthenticationModule as WSFederationAuthenticationModule;
        if (federatedModule != null)
        {
            federatedModule.PassiveRedirectEnabled = true;

            if (!String.IsNullOrEmpty(RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationRequireHttps")))
            {
                federatedModule.RequireHttps = bool.Parse(RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationRequireHttps"));
            }
            if (!String.IsNullOrEmpty(RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationIssuer")))
            {
                federatedModule.Issuer = RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationIssuer");
            }
            if (!String.IsNullOrEmpty(RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationRealm")))
            {
                federatedModule.Realm = RoleEnvironment.GetConfigurationSettingValue("FedAuthWSFederationRealm");
            }

            CookieHandler cookieHandler = FederatedAuthentication.SessionAuthenticationModule.CookieHandler;
            cookieHandler.RequireSsl = false;
        }
        else
        {
            Trace.TraceError("Unable to configure the federated module. The modules weren't loaded.");
        }
    }
}

Это позволит вам настроить следующие параметры во время выполнения:

  <Setting name="FedAuthAudienceUri" value="-- update with audience url. e.g. https://yourwebsite/ --" />
  <Setting name="FedAuthWSFederationIssuer" value="-- update with WSFederation endpoint. e.g. https://yourissuer/v2/wsfederation--" />
  <Setting name="FedAuthWSFederationRealm" value="-- update with WSFederation realm. e.g. https://yourwebsite/" />
  <Setting name="FedAuthTrustedIssuerThumbprint" value="-- update with certificate thumbprint from ACS configuration. e.g. cb27dd190485afe0f62e470e4e3578de51d52bf4--" />
  <Setting name="FedAuthTrustedIssuerName" value="-- update with issuer name. e.g. https://yourissuer/--" />
  <Setting name="FedAuthServiceCertificateThumbprint" value="-- update with service certificate thumbprint. e.g. same as HTTPS thumbprint: FE95C43CD4C4F1FC6BC1CA4349C3FF60433648DB --" />
  <Setting name="FedAuthWSFederationRequireHttps" value="true" />
...