ASP.NET Core 1.x提供了通過Cookie "中間件" 將用戶主體序列化為一個加密的Cookie,然後在後續請求中驗證Cookie並重新創建主體,並將其分配給 屬性。如果您要提供自己的登錄界面和用戶資料庫,可以使用作為獨立功能的Cookie中間件。 ASP.NET Core 2.x的一個 ...
ASP.NET Core 1.x提供了通過Cookie 中間件將用戶主體序列化為一個加密的Cookie,然後在後續請求中驗證Cookie並重新創建主體,並將其分配給HttpContext.User
屬性。如果您要提供自己的登錄界面和用戶資料庫,可以使用作為獨立功能的Cookie中間件。
ASP.NET Core 2.x的一個主要變化是不再存在Cookie中間件。取而代之的是在Startup.cs文件中的Configure
方法中的調用UseAuthentication
方法會添加設置HttpContext.User
屬性的 AuthenticationMiddleware 中間件。
添加配置
ASP.NET Core 1.x
按下列步驟操作:
在您的項目中安裝
Microsoft.AspNetCore.Authentication.Cookies
NuGet包。此包包含Cookie中間件。在Startup.cs文件中的
Configure
方法中添加下麵的行,在app.UseMvc()
語句之前:app.UseCookieAuthentication(new CookieAuthenticationOptions() { AccessDeniedPath = "/Account/Forbidden/", AuthenticationScheme = "MyCookieAuthenticationScheme", AutomaticAuthenticate = true, AutomaticChallenge = true, LoginPath = "/Account/Unauthorized/" });
ASP.NET Core 2.x
按下列步驟操作:
如果不使用
Microsoft.AspNetCore.All
元包,則在您的項目中安裝2.0版的Microsoft.AspNetCore.Authentication.Cookies
NuGet包。在Startup.cs文件中的
Configure
方法中調用UseAuthentication
方法:app.UseAuthentication();
在Startup.cs文件中的
ConfigureServices
方法中調用AddAuthentication
和AddCookie
方法:services.AddAuthentication("MyCookieAuthenticationScheme") .AddCookie(options => { options.AccessDeniedPath = "/Account/Forbidden/"; options.LoginPath = "/Account/Unauthorized/"; });
上面的代碼片段配置了以下部分或全部選項:
AccessDeniedPath
- 當用戶嘗試訪問資源但沒有通過任何授權策略時,這是請求會重定向的相對路徑資源。AuthenticationScheme
- 這是一個已知的特定Cookie認證方案的值。當有多個Cookie驗證實例,並且您想限制對一個實例的授權時,這就非常有用。AutomaticAuthenticate
- 此標識僅適用於ASP.NET Core 1.x。它表示Cookie身份驗證應在每個請求上運行,並嘗試驗證和重建序列化主體。AutomaticChallenge
- 此標識僅適用於ASP.NET Core 1.x。這表示當授權失敗時,1.x Cookie認證應將瀏覽器重定向到LoginPath
或AccessDeniedPath
。LoginPath
- 當用戶嘗試訪問資源但尚未認證時,這是請求重定向的相對路徑。
其它選項包括為Cookie認證創建的設置選項,身份驗證的Cookie的名稱,Cookie的域和Cookie各種安全屬性。預設情況下,Cookie身份驗證為其創建的任何Cookie使用適當的安全選項,例如:
- 設置HttpOnly標誌以防止客戶端JavaScript中訪問Cookie
- 如果請求是通過HTTPS訪問,則將Cookie限製為HTTPS
創建身份認證Cookie
要創建一個保存用戶信息的cookie,您必須構建一個ClaimsPrincipal 保存您希望序列化到Cookie中的信息。
ASP.NET Core 1.x
await HttpContext.Authentication.SignInAsync("MyCookieAuthenticationScheme", principal);
ASP.NET Core 2.x
await HttpContext.SignInAsync("MyCookieAuthenticationScheme", principal);
這將創建一個加密的Cookie並將其添加到當前響應中。在調用SignInAsync
時,必須在配置中指定的AuthenticationScheme
。
順便提一下,使用的加密方式是ASP.NET Core的Data Protection系統。如果您在多台機器上進行托管、負載平衡或使用Web集群,則需要配置Data Protection才能使用相同的密鑰和應用程式標識符。
Signing out(登出)
要退出當前用戶並刪除其Cookie,請在控制器中調用以下方法:
ASP.NET Core 1.x
await HttpContext.Authentication.SignOutAsync("MyCookieAuthenticationScheme");
ASP.NET Core 2.x
await HttpContext.SignOutAsync("MyCookieAuthenticationScheme");
服務端變化反饋
警告: 一旦創建了認證的Cookie,它將成為唯一的身份來源。即使您在服務系統中禁用用戶,Cookie身份驗證也無法瞭解此信息,只要Cookie有效,用戶仍可登錄。
Cookie認證在其選項中提供了一系列事件。ValidateAsync()
事件可用於攔截和重寫Cookie身份驗證。
可以考慮在後端用戶資料庫中增加LastChanged
列。為了在資料庫更改時使Cookie無效,您應該首先在創建Cookie時添加一個LastChanged
包含當前值的聲明。資料庫更改時,更新LastChanged
例的值。
要重寫ValidateAsync()
事件的實現,您必須編寫一個具有以下簽名的方法:
Task ValidateAsync(CookieValidatePrincipalContext context);
ASP.NET Core Identity 在SecurityStampValidator
實現了這一邏輯,鏈接地址。示例如下所示:
ASP.NET Core 1.x
public static class LastChangedValidator
{
public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
// Pull database from registered DI services.
var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
var userPrincipal = context.Principal;
// Look for the last changed claim.
string lastChanged;
lastChanged = (from c in userPrincipal.Claims
where c.Type == "LastUpdated"
select c.Value).FirstOrDefault();
if (string.IsNullOrEmpty(lastChanged) ||
!userRepository.ValidateLastChanged(userPrincipal, lastChanged))
{
context.RejectPrincipal();
await context.HttpContext.Authentication.SignOutAsync("MyCookieAuthenticationScheme");
}
}
}
然後,在Startup.cs文件中的Configure
方法中將Cokie認證配置進行重寫:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = LastChangedValidator.ValidateAsync
}
});
ASP.NET Core 2.x
public static class LastChangedValidator
{
public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
// Pull database from registered DI services.
var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
var userPrincipal = context.Principal;
// Look for the last changed claim.
string lastChanged;
lastChanged = (from c in userPrincipal.Claims
where c.Type == "LastUpdated"
select c.Value).FirstOrDefault();
if (string.IsNullOrEmpty(lastChanged) ||
!userRepository.ValidateLastChanged(userPrincipal, lastChanged))
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync("MyCookieAuthenticationScheme");
}
}
}
然後,將在Startup.cs的ConfigureServices
方法中將Cookie服務註冊進行配置:
services.AddAuthentication("MyCookieAuthenticationScheme")
.AddCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = LastChangedValidator.ValidateAsync
};
});
如果要非破壞性地更新用戶主體,可以調用context.ReplacePrincipal()
,並將context.ShouldRenew
屬性設置為true
。
Cookie設置選項
CookieAuthenticationOptions類提供了各種配置選項,在創建時調整Cookie的配置。
ASP.NET Core 1.x
ClaimsIssuer
是由中間件創建的任何聲明時使用的Issuer屬性。CookieDomain
是提供Cookie的功能變數名稱。預設情況下,這是發送請求的主機名。瀏覽器僅將Cookie提供給匹配的主機名。您可能希望對此進行調整,以便您的域中的任何主機都可以使用Cookie。例如,將Cookie功能變數名稱設置為.contoso.com
,可以使用Cookie的功能變數名稱有contoso.com
、www.contoso.com
、staging.www.contoso.com
等。CookieHttpOnly
是一個標識,指定Cookie是否只能由伺服器訪問。預設為true
。如果您的應用程式具有Cross-Site Scripting(XSS)的問題,更改此值可能會導致Cookie被盜用。CookiePath
可用於隔離在相同主機名上運行的應用程式。如果你有一個應用程式在/app1
中運行,並希望限制發送的Cookie只發送到該應用程式,那麼您應該將CookiePath
屬性設置為/app1
。通過這樣做,Cookie只適用於對/app1
或其下任何內容的請求。CookieSecure
是一個標識,表示創建的Cookie是否應該被限製為HTTPS,HTTP或HTTPS,或與請求相同的協議。預設為SameAsRequest
。ExpireTimeSpan
是TimeSpan
類型,在此時間段之後Cookie將過期。將當前日期加上此時間段為創建Cookie的到期日期。SlidingExpiration
是一個標識,指示當超過一半的ExpireTimeSpan
間隔時,Cookie到期日期是否複位。新的到期日是當前時間加上ExpireTimespan
。調用SignInAsync
時,可以使用AuthenticationProperties
類設置絕對到期時間。絕對到期時間可以通過限制認證Cookie有效的時間來提高應用程式的安全性。
在Startup.cs文件中的Configure
方法中使用CookieAuthenticationOptions
的例子如下:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "AuthCookie",
CookieDomain = "contoso.com",
CookiePath = "/",
CookieHttpOnly = true,
CookieSecure = CookieSecurePolicy.Always
});
ASP.NET Core 2.x
ASP.NET Core 2.x 統一了用於配置Cookie的API。1.x API已被標記為過時,並且在CookieAuthenticationOptions
類中引入了一種類型為CookieBuilder
新的Cookie
屬性。建議您遷移到2.x API。
ClaimsIssuer
是由Cookie認證創建的任何聲明時使用的Issuer屬性。CookieBuilder.Domain
是提供Cookie的功能變數名稱。預設情況下,這是發送請求的主機名。瀏覽器僅將Cookie提供給匹配的主機名。您可能希望對此進行調整,以便您的域中的任何主機都可以使用Cookie。例如,將Cookie功能變數名稱設置為.contoso.com
,可以使用Cookie的功能變數名稱有contoso.com
、www.contoso.com
、staging.www.contoso.com
等CookieBuilder.HttpOnly
是一個標識,指定Cookie是否只能由伺服器訪問。預設為true
。如果您的應用程式具有Cross-Site Scripting(XSS)的問題,更改此值可能會導致Cookie被盜用。CookieBuilder.Path
可用於隔離在相同主機名上運行的應用程式。如果你有一個應用程式在/app1
中運行,並希望限制發送的Cookie只發送到該應用程式,那麼您應該將CookiePath
屬性設置為/app1
。通過這樣做,Cookie只適用於對/app1
或其下任何內容的請求。CookieBuilder.SameSite
表示瀏覽器是否允許Cookie被附加到同一站點或跨站點的請求。預設為SameSiteMode.Lax
。CookieBuilder.SecurePolicy
是一個標識,表示創建的Cookie是否應該被限製為HTTPS,HTTP或HTTPS,或與請求相同的協議。預設為SameAsRequest
。ExpireTimeSpan
是TimeSpan
類型,在此時間段之後Cookie將過期。將當前日期加上此時間段為創建Cookie的到期日期。SlidingExpiration
是一個標識,指示當超過一半的ExpireTimeSpan
間隔時,Cookie到期日期是否複位。新的到期日是當前時間加上ExpireTimespan
。調用SignInAsync
時,可以使用AuthenticationProperties
類設置絕對到期時間。絕對到期時間可以通過限制認證Cookie有效的時間來提高應用程式的安全性。
在Startup.cs的ConfigureServices
方法中使用CookieAuthenticationOptions
的例子如下:
services.AddAuthentication()
.AddCookie(options =>
{
options.Cookie.Name = "AuthCookie";
options.Cookie.Domain = "contoso.com";
options.Cookie.Path = "/";
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
持久Cookie和絕對到期時間
您可能希望Cookie在瀏覽器會話中持續存在,並希望設置身份和Cookie傳輸的絕對過期時間。這種持久性應該只能是用戶顯示同意,在登錄時的“記住我”覆選框或類似的機制啟用。您可以通過在創建身份認證Cookie時調用的SignInAsync
方法中使用AuthenticationProperties
參數來執行這些操作。例如:
ASP.NET Core 1.x
await HttpContext.Authentication.SignInAsync(
"MyCookieAuthenticationScheme",
principal,
new AuthenticationProperties
{
IsPersistent = true
});
上述代碼片段中使用的AuthenticationProperties
類,位於Microsoft.AspNetCore.Http.Authentication
命名空間中。
ASP.NET Core 2.x
await HttpContext.SignInAsync(
"MyCookieAuthenticationScheme",
principal,
new AuthenticationProperties
{
IsPersistent = true
});
上述代碼片段中使用的AuthenticationProperties
類,位於Microsoft.AspNetCore.Authentication
命名空間中。
上面的代碼段創建一個身份和相應的Cookie,直到瀏覽器關閉。以前通過Cookie設置選項配置的任何滑動過期設置仍然有效。如果Cookie在瀏覽器關閉時過期,瀏覽器會在重新啟動後清除它。如果Cookie在瀏覽器關閉時過期,瀏覽器會在重新啟動後清除它。
ASP.NET Core 1.x
await HttpContext.Authentication.SignInAsync(
"MyCookieAuthenticationScheme",
principal,
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
});
ASP.NET Core 2.x
await HttpContext.SignInAsync(
"MyCookieAuthenticationScheme",
principal,
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
});
上述代碼段創建一個持續20分鐘的身份和相應的cookie。這將忽略以前通過Cookie設置選項配置的任何滑動過期設置。
ExpiresUtc
和IsPersistent
屬性是互斥的。
原文:《Using Cookie Authentication without ASP.NET Core Identity》https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x
翻譯:Sweet Tang
本文地址:<http://www.cnblogs.com/tdfblog/p/aspnet-core-security-authentication-cookie.html >
歡迎轉載,請在明顯位置給出出處及鏈接。