ASP.NET Core 3.1 Razor Pages SameSite cookie 示例
ASP.NET Core 3.0 对 SameSite 属性提供内置支持,包括用于禁止写入该属性的 SameSiteMode
属性值 Unspecified
。
ASP.NET Core Identity 在很大程度上不受 SameSite Cookie 的影响,但 IFrames
或 OpenIdConnect
集成等高级方案除外。
使用 Identity
时,不要添加任何 cookie 提供程序或调用 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
,Identity
会执行这些操作。
写入 SameSite 属性
以下示例介绍如何在 cookie 上写入 SameSite 属性:
var cookieOptions = new CookieOptions
{
// Set the secure flag, which Chrome's changes will require for SameSite none.
// Note this will also require you to be running on HTTPS
Secure = true,
// Set the cookie to HTTP only which is good practice unless you really do need
// to access it client side in scripts.
HttpOnly = true,
// Add the SameSite attribute, this will emit the attribute with a value of none.
// To not emit the attribute at all set the SameSite property to SameSiteMode.Unspecified.
SameSite = SameSiteMode.None
};
// Add the cookie to the response cookie collection
Response.Cookies.Append(CookieName, "cookieValue", cookieOptions);
设置 Cookie 身份验证和会话状态 Cookie
Cookie 身份验证、会话状态和各种其他组件通过 Cookie 选项设置其 sameSite 选项,例如
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
services.AddSession(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
在上面显示的代码中,cookie 身份验证和会话状态都将其 sameSite 属性设置为 None,发出值为 None
的属性,并将 Secure 属性设置为 true。
运行示例
如果运行的是示例项目,请在初始页面上加载浏览器调试器并使用该调试器查看站点的 cookie 集合。 若要在 Edge 和 Chrome 中执行此操作,请按 F12
,然后选择 Application
选项卡并单击 Storage
部分中 Cookies
选项下的站点 URL。
从上图中可以看出,单击“创建 SameSite Cookie”按钮时,由示例创建的 cookie 的 SameSite 属性值为 Lax
,该值与示例代码中设置的值相匹配。
截获 Cookie
为了截获 Cookie,以便根据用户浏览器代理的支持调整 none 值,必须使用 CookiePolicy
中间件。 必须将其放置在 HTTP 请求管道中,且要置于任何写入 Cookie 的组件之前,并在 ConfigureServices()
中进行配置。
若要将其插入管道,请在 Startup.cs 的 Configure(IApplicationBuilder, IHostingEnvironment)
方法中使用 app.UseCookiePolicy()
。 例如:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
然后在 ConfigureServices(IServiceCollection services)
中配置 cookie 策略,以便在追加或删除 Cookie 时调用帮助程序类,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
}
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (SameSite.BrowserDetection.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
}
}
帮助程序函数 CheckSameSite(HttpContext, CookieOptions)
:
- 将 Cookie 追加到请求或从请求中删除 Cookie 时调用。
- 检查
SameSite
属性是否设置为None
。 - 如果
SameSite
设置为None
并且已知当前用户代理不支持 none 属性值。 使用 SameSiteSupport 类完成检查:- 将
SameSite
设置为不发出值,方法是将该属性设置为(SameSiteMode)(-1)
- 将