Я боролся с тем же и нашел рабочее решение в WIF 3.5/4.0. Поскольку ссылка maartenba кажется мертвой, я хотел опубликовать здесь свое решение.
Нашими требованиями были:
- Конфигурация полностью в коде (поскольку мы отправляем файл web.config по умолчанию с приложением)
- Максимально допустимая версия .Net 4.0 (поэтому я использую WIF 3.5/4.0)
Что я использовал, чтобы прийти к решению:
- Информация о динамической конфигурации WIF предоставлена Дэниелом Ву здесь.
- Этот метод для регистрации модулей HTTP на время выполнения, объясненное Дэвидом Эббо. Я также попробовал более элегантный метод , объясненный Риком Стралом., но, к сожалению, мне это не помогло.
Изменить 2016/09/02: вместо добавления отдельного класса «стартового кода перед приложением», как в примере Дэвида Эббо, HTTP-модули, связанные с WIF, также могут быть зарегистрированы в статическом конструкторе класса «HttpApplication». Я адаптировал код к этому несколько более чистому решению.
Моему решению ничего не нужно в файле web.config. Основная часть кода находится в файле global.asax.cs. Конфигурация в этом примере жестко запрограммирована:
using System;
using System.IdentityModel.Selectors;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Web;
namespace TestADFS
{
public class SessionAuthenticationModule : Microsoft.IdentityModel.Web.SessionAuthenticationModule
{
protected override void InitializePropertiesFromConfiguration(string serviceName)
{
}
}
public class WSFederationAuthenticationModule : Microsoft.IdentityModel.Web.WSFederationAuthenticationModule
{
protected override void InitializePropertiesFromConfiguration(string serviceName)
{
ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
PassiveRedirectEnabled = true;
RequireHttps = true;
Issuer = "https://nl-joinadfstest.joinadfstest.local/adfs/ls/";
Realm = "https://67px95j.decos.com/testadfs";
}
}
public class Global : HttpApplication
{
static Global()
{
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(SessionAuthenticationModule));
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(WSFederationAuthenticationModule));
}
protected void Application_Start(object sender, EventArgs e)
{
FederatedAuthentication.ServiceConfigurationCreated += FederatedAuthentication_ServiceConfigurationCreated;
}
internal void FederatedAuthentication_ServiceConfigurationCreated(object sender, Microsoft.IdentityModel.Web.Configuration.ServiceConfigurationCreatedEventArgs e)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByThumbprint, "245537E9BB2C086D3C880982FA86267FBD66B9A3", false);
if (coll.Count > 0)
e.ServiceConfiguration.ServiceCertificate = coll[0];
store.Close();
AudienceRestriction ar = new AudienceRestriction(AudienceUriMode.Always);
ar.AllowedAudienceUris.Add(new Uri("https://67px95j.decos.com/testadfs"));
e.ServiceConfiguration.AudienceRestriction = ar;
ConfigurationBasedIssuerNameRegistry inr = new ConfigurationBasedIssuerNameRegistry();
inr.AddTrustedIssuer("6C9B96D90257B65B6F181C2478D869473DC359EA", "http://NL-JOINADFSTEST.joinadfstest.local/adfs/services/trust");
e.ServiceConfiguration.IssuerNameRegistry = inr;
e.ServiceConfiguration.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
FederatedAuthentication.WSFederationAuthenticationModule.ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
}
}
}
использование
Мое приложение — asp.net WebForms, работает в классическом конвейерном режиме и поддерживает проверку подлинности с помощью форм, а также вход в ADFS. Из-за этого аутентификация обрабатывается в общем базовом классе, совместно используемом всеми страницами .aspx:
protected override void OnInit(EventArgs e)
{
if (NeedsAuthentication && !User.Identity.IsAuthenticated)
{
SignInRequestMessage sirm = new SignInRequestMessage(
new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
ApplicationRootUrl)
{
Context = ApplicationRootUrl,
HomeRealm = ApplicationRootUrl
};
Response.Redirect(sirm.WriteQueryString());
}
base.OnInit(e);
}
В этом коде ApplicationRootUrl
— это путь к приложению, оканчивающийся на «/» («/» важен в классическом конвейерном режиме).
Поскольку стабильная реализация выхода из смешанного режима была не такой уж простой, я хочу показать код и для этого. Технически это работает, но у меня все еще есть проблема с повторным входом в IE после выхода из учетной записи ADFS:
if (User.Identity.IsAuthenticated)
{
if (User.Identity.AuthenticationType == "Forms")
{
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
ResetCookie(FormsAuthentication.FormsCookieName);
ResetCookie("ASP.NET_SessionId");
Response.Redirect(ApplicationRootUrl + "Default.aspx");
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
else
{
FederatedAuthentication.SessionAuthenticationModule.SignOut();
FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
Uri uri = new Uri(ApplicationRootUrl + "Default.aspx");
WSFederationAuthenticationModule.FederatedSignOut(
new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
uri); // 1st url is single logout service binding from adfs metadata
}
}
(ResetCookie
— это вспомогательная функция, которая очищает файл cookie ответа и устанавливает срок его действия в прошлом)
person
Berend Engelbrecht
schedule
01.09.2016