在 ASP.NET 中設定 SameSite Cookies
TLDR
- SameSite 屬性用於限制第三方 Cookie 的發送,以防禦 CSRF 攻擊。
- SameSite 共有三個值:
None(所有請求發送)、Lax(預設值,僅第一方或連結請求發送)、Strict(僅第一方請求發送)。 - 在 ASP.NET Core 中,建議透過
CookiePolicyOptions進行全域設定,並針對舊版瀏覽器實作User-Agent檢測以處理None值的相容性。 - 在 ASP.NET Framework 4.7.2+ 中,可透過
Web.config的httpCookies節點設定全域預設值。 ASP.NET_SessionId的 SameSite 行為受<sessionState>設定影響,需特別注意。- 瀏覽器對 SameSite 的實作存在差異,開發時應考慮相容性與測試環境(如使用無痕模式)。
SameSite Cookies 核心概念
SameSite 是 IETF 訂立的標準,旨在限制第三方 Cookie 的傳輸,從而降低跨網站要求偽造 (CSRF) 的風險。
Same-Site 屬性值說明
| 值 | 說明 |
|---|---|
None | Cookie 將在所有請求中發送,現今必須搭配 Secure 屬性。 |
Lax | 現今瀏覽器的預設值,僅在第一方上下文或用戶透過連結導向時發送。 |
Strict | Cookie 僅會在第一方上下文的請求中發送。 |
什麼情況下會遇到問題?
當應用程式依賴第三方 Cookie(如跨網域的 iframe 嵌入或 AJAX 請求)時,若設定為 Lax 或 Strict,會導致 Cookie 無法被正確讀取,造成使用者登入狀態失效或功能異常。
WARNING
瀏覽器對 SameSite 的實作並非完全一致。早期版本對未設定 SameSite 的處理方式不盡相同,且 None 值在舊版瀏覽器中可能不被支援,需透過 User-Agent 偵測進行降級處理。
在 ASP.NET Core 設定 SameSite Cookies
全域設定方式
透過 Program.cs 中的 CookiePolicyOptions 進行全域控管,並確保 app.UseCookiePolicy() 放置在 app.UseAuthorization() 之前。
csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options => {
// 設定最低層級限制
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
// 處理舊版瀏覽器相容性
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
void CheckSameSite(HttpContext httpContext, CookieOptions options) {
if (options.SameSite == SameSiteMode.None) {
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (DisallowsSameSiteNone(userAgent)) {
options.SameSite = SameSiteMode.Unspecified;
}
}
}個別 Cookie 設定
若需針對特定 Cookie 進行設定,可直接在 CookieOptions 中指定:
csharp
Response.Cookies.Append("name", "value", new CookieOptions() {
SameSite = SameSiteMode.Lax
});在 ASP.NET Framework 設定 SameSite Cookies
此功能需在 Framework 4.7.2 以上版本使用。
Web.config 全域設定
若個別 Cookie 未指定 SameSite,系統將採用 httpCookies 的預設值。
xml
<configuration>
<system.web>
<httpCookies sameSite="Lax"></httpCookies>
</system.web>
</configuration>舊瀏覽器相容性處理
在 Global.asax.cs 中攔截請求並過濾不支援 None 的瀏覽器:
csharp
protected void Application_BeginRequest(object sender, EventArgs e) {
HttpApplication application = sender as HttpApplication;
var userAgent = application.Context.Request.UserAgent;
if (DisallowsSameSiteNone(userAgent)) {
HttpContext.Current.Response.AddOnSendingHeaders(context => {
var cookies = context.Response.Cookies;
for (var i = 0; i < cookies.Count; i++) {
if (cookies[i].SameSite == SameSiteMode.None) {
cookies[i].SameSite = (SameSiteMode)(-1); // 設為 Unspecified
}
}
});
}
}TIP
ASP.NET_SessionId 的 SameSite 設定通常由 <sessionState cookieSameSite="..." /> 控制,而非 httpCookies。測試時建議使用無痕模式,以避免既有 Cookie 影響測試結果。
異動歷程
- 初版文件建立。