Technologie Windows Identity Foundation (WIF) (dříve také znám pod označením projekt “Geneva”) již nějakou tu chvilku existuje, a to zatím v podobě přídavné knihovny. Dá se předpokládat, že většího rozšíření této technologie se pravděpodobně dočkáme až se stane součástí přímo .NET Frameworku tj. až ve verzi .NET Frameworku 4.5. Dnes si ukážeme pro ní možná trochu netradiční použití - příklad jednoduché webové aplikace, která využívá WIF jako náhradu za Forms autentizaci.
Příklad není nijak zvlášť rozsáhlý, jedná se o jediný VS projekt samostatné webové aplikace běžící v IIS pod Frameworkem 4.0. Příklad nepoužívá žádné STS (Security Token Service), ACS, Federation metadata a podobné další součásti WIF (tj. pokud vám tyto pojmy nic neříkají nebude to vadit). Aplikace používá WIF pouze pro ověřování pomoci claimů, těmto aplikacím se také někdy říká claims-aware aplikace.
Nejprve je potřeba do systému nainstalovat runtime pro tuto technologii z Microsoft Download centra, pro Windows Vista/2008, 7/2008 R2 zde , pro Windows 2003 zde (ve Windows XP již není tato technologie podporována). Tím se nám zároveň nainstaluje i potřebná assembly Microsoft.IdentityModel.dll do umístění C:\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5.
Dále je možné stáhnout a doinstalovat také Windows Identity Foundation SDK obsahující příklady a podporu do VS (pro tento příklad není toto SDK ale potřeba).
V tomto článku jsem detailněji psal o principu fungování Forms autentizace. Pokud jste tak neučili, doporučuji si ho pro lepší srovnání s dnešním příkladem nejprve také projít.
Kompletní zdrojový projekt příkladu je ke stažení k dispozici zde.
(Update: Verze pro .NET Framework 4.5 je k dispozici zde.)
Příklad se zaměřuje na následující:
- Možnost provedení vlastního způsobu ověření uživatele (zde by například bylo možné volat membership provider). Po ověření se provádí vystavení objektu ClaimsPrincipal, který obsahuje vlastní data – sadu claims – a reprezentuje přihlášeného uživatele. V příkladu jsou tyto data i ověření uživatele “natvrdo”.
Toto je realizováno v metodě Authenticate třídy AuthenticationManager v obsluze odeslání přihlašovacího formuláře (v codebehind stránky Login.aspx).
var claimsPrincipal = AuthenticationManager.Authenticate(txtUsername.Text, txtPassword.Text);
Tato metoda má za úkol provést ověření přihlašovacích údajů uživatele (přihlašovací jméno a heslo) a získat objekt IClaimsPrincipal. Ověření a konstrukci objektu ClaimsPrincipal odpovídá tento kód:
if (userName == "admin" && password == "password") //Custom claims
{
var outputIdentity = new ClaimsIdentity("Custom");
outputIdentity.Claims.Add(new Claim(ClaimTypes.Name, userName));
outputIdentity.Claims.Add(new Claim(ClaimTypes.Role, "Administrators"));
outputIdentity.Claims.Add(new Claim(ClaimTypes.Email, "[email protected]"));
outputIdentity.Claims.Add(new Claim(ClaimTypes.Gender, "Male"));
outputIdentity.Claims.Add(new Claim("UserId", "10", "int"));
return ClaimsPrincipal.CreateFromIdentity(outputIdentity);
}
- Ověřování Windows uživatele pomoci WindowsUserNameSecurityTokenHandler handleru. Příklad využívá výchozí konfigurace WIF infrastruktury, kdy jsou přihlašovací údaje (přihlašovací jméno a heslo) – UserNameSecurityToken – ověřovány jako uživatel Windows (ve výchozí nebo doméně uvedené v přihlašovacím jménu). Konfigurace Security token handlerů se provádí v souboru web.config v sekci <microsoft.identityModel> <service> <securityTokenHandlers>.
Toto je realizováno ve třídě AuthenticationManager pomocnou metodou ValidateWindowsUser. Tato metoda je volána z metody Authenticate.
SecurityToken securityToken = new UserNameSecurityToken(userName, password);
var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
//Uses default WindowsUserNameSecurityTokenHandler
var principal = ClaimsPrincipal.CreateFromIdentities(handlers.ValidateToken(securityToken));
return principal;
Tímto ověřením je získán objekt WindowsClaimsPrincipal, který součástí svých claims obsahuje SID uživatele i SIDy všech jeho členských skupin (využitelné pro autorizaci).
- Příklad používá SessionAuthenticationModule pro uchovávání informací o aktuálně přihlášeném uživateli v podobě session security tokenu ukládaného v cookie. Jedná se o mechanismus pro autentizaci klientských requestů obdobně jako u Forms autentizace, na rozdíl od Forms autentizačního tiketu ale session security token umožňuje serializovat a následně rekonstruovat objekt IClaimsPrincipal včetně všech obsažených claims. Příklad podporuje i volbu “Zůstat přihlášen(a)” přihlašovacího dialogu pro zapamatování přihlášení tj. vytvoření perzistentního cookie.
Toto je realizované jednak registrací modulu SessionAuthenticationModule v konfiguračním souboru web.config a jednak metodou SetAuthCookie třídy WIFAuthentication. Tato metoda je volaná po ověření uživatele metodou AuthenticationManager.Authenticate po získání objektu IClaimsPrincipal.
var claimsPrincipal = AuthenticationManager.Authenticate(txtUsername.Text, txtPassword.Text);
WIFAuthentication.SetAuthCookie(claimsPrincipal, chckRememberMe.Checked);
Metoda sestavuje session security token, který následně zapíše jako hodnotu cookie do aktuálního response.
var sessionAuthenticationModule = FederatedAuthentication.SessionAuthenticationModule;
var sessionToken = sessionAuthenticationModule.CreateSessionSecurityToken(claimsPrincipal, null,
DateTime.UtcNow,
DateTime.UtcNow.Add(ConfiguredSessionTokenLifeTime),
createPersistentCookie);
sessionAuthenticationModule.CookieHandler.RequireSsl = false;
sessionAuthenticationModule.AuthenticateSessionSecurityToken(sessionToken, true);
- Pokud je uživatel přihlášen, je zobrazena výchozí stránka default.aspx, která obsahuje výpis všech claims aktuálního uživatele.
Identita přihlášeného uživatele je přitom dostupná například kódem:
if (Page.User.Identity.IsAuthenticated)
{
IClaimsIdentity claimsIdentity = Page.User.Identity as IClaimsIdentity;
if (claimsIdentity != null)
{
//...
}
}
Tento příklad by měl ukázat, jak použití WIF infrastruktury odstraňuje některé nevýhody Forms autentizace.
Do objektu IClaimsPrincipal můžeme v podobě claims schovat libovolné informace, které o přihlášeném uživateli potřebujeme (například UserId, email, nebo seznam rolí pro autorizaci). Všechny tyto informace jsou pak automaticky přenášeny mezi jednotlivými requesty a tedy kdykoliv okamžitě dostupné. Lze použít vlastní i standardní typy ověřování i umožnit souběh několika způsobů.