ASP.NET和ASP.NET Core中即将进行的SameSite Cookie更改

SameSite是一个2016 HTTP cookie扩展,旨在防止跨站点请求伪造(CSRF)。 最初,它的设计是一项附加功能,可以通过向cookie添加新的SameSite属性来使用。 它有两个含义,宽松和严格。

设置Lax值时,这意味着应在浏览一个站点或通过GET从其他站点浏览到您的站点时发送cookie。 “严格”值将cookie限制为仅来自一个站点的请求。 缺少设置任何属性不会对cookie在请求中的工作方式施加任何限制。 将外部站点的POST请求发送到请求该操作的站点的OpenIdConnect身份验证操作(例如,登录,注销)和其他功能可以使用Cookie关联和/或保护CSRF。 这些操作将不得不拒绝SameSite,而无需设置任何属性,以确保这些cookie将在其特殊请求流期间发送。

Google目前正在更新标准,并在Chrome的未来版本中引入建议的更改。 所做的更改将添加相同的SameSite“无”值,并将默认行为更改为“松散”。 这会破坏OpenIdConnect登录名以及您的网站可以建立的其他功能。 这些功能将需要使用SameSite属性设置为None的cookie。

但是,遵循原始标准并且不知道新值的浏览器的行为与使用新标准的浏览器不同。 这意味着您的.NET网站现在将需要添加用户代理嗅探,以决定是否发送新的None值或根本不发送属性。



.NET将收到更新,以更改.NET 4.7.2和.NET Core 2.1以及更高版本中SameSite属性的行为,以适应Google对新值的引入。 如果您使用“检查更新”功能,.NET Framework的更新将于11月19日作为Microsoft Update和WSUS的附加更新发布。 该更新将于12月10日公开发布,并将出现在Microsoft Update Center中。 .NET Core更新将在11月发布的.NET Core 3.1中从预览版1开始提供。

.NET Core 3.1将包含更新的枚举定义 SameSite.Unspecified,该定义不会设置SameSite属性。

用于Microsoft.Owin v4.1和.NET Core的OpenIdConnect中间件将与.NET Framework和.NET的更新同时进行更新,但是,我们无法将用户代理嗅探代码添加到框架中,应在您站点的代码中实现。 代理嗅探的实现将取决于您所使用的ASP.NET或ASP.NET Core版本以及要支持的浏览器。

对于带有Microsoft.Owin 4.1.0的ASP.NET 4.7.2,可以使用ICookieManager来实现代理嗅探。

public class SameSiteCookieManager : ICookieManager { private readonly ICookieManager _innerManager; public SameSiteCookieManager() : this(new CookieManager()) { } public SameSiteCookieManager(ICookieManager innerManager) { _innerManager = innerManager; } public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options) { CheckSameSite(context, options); _innerManager.AppendResponseCookie(context, key, value, options); } public void DeleteCookie(IOwinContext context, string key, CookieOptions options) { CheckSameSite(context, options); _innerManager.DeleteCookie(context, key, options); } public string GetRequestCookie(IOwinContext context, string key) { return _innerManager.GetRequestCookie(context, key); } private void CheckSameSite(IOwinContext context, CookieOptions options) { if (DisallowsSameSiteNone(context) && options.SameSite == SameSiteMode.None) { options.SameSite = null; } } public static bool DisallowsSameSiteNone(IOwinContext context) { // TODO:    User Agent . var userAgent = context.Request.Headers["User-Agent"]; return userAgent.Contains("BrokenUserAgent") || userAgent.Contains("BrokenUserAgent2") } } 

然后配置OpenIdConnect设置以使用新的CookieManager;

 app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // …    … CookieManager = new SameSiteCookieManager(new SystemWebCookieManager()) }); 

为了使SystemWebCookieManager正常运行,您将需要安装固定的SameSite .NET 4.7.2或更高版本。

对于ASP.NET Core,必须安装补丁,然后将代理嗅探代码注入cookie策略 。 对于3.1之前的版本,将SameSiteMode.Unspecified替换为(SameSiteMode)(-1)。

 private void CheckSameSite(HttpContext httpContext, CookieOptions options) { if (options.SameSite > SameSiteMode.Unspecified) { var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); // TODO:    User Agent . if (/* UserAgent doesn't support new behavior */) { //  .NET Core < 3.1  SameSite = -1 options.SameSite = SameSiteMode.Unspecified; } } } public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.Unspecified; options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); }); } public void Configure(IApplicationBuilder app) { app.UseCookiePolicy(); // Before UseAuthentication or anything else that writes cookies. app.UseAuthentication(); // … } 

在与Azure Active Directory团队进行测试时,我们发现以下检查适用于根据Azure Active Directory不理解新值的所有普通用户代理。

 public static bool DisallowsSameSiteNone(string userAgent) {    //      iOS.   :    // - Safari  iOS 12  iPhone, iPod Touch, iPad    // - WkWebview  iOS 12  iPhone, iPod Touch, iPad    // - Chrome  iOS 12  iPhone, iPod Touch, iPad    if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))    {        return true;    }    //     Mac OS X.   :    // - Safari  Mac OS X.    //  :    // - Chrome  Mac OS X    //        Mac OS.    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") && userAgent.Contains("Version/") && userAgent.Contains("Safari"))    {        return true;    }    //    Chrome 50-69,      SameSite=None.    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))    {        return true;    }    return false; } 

此浏览器列表绝对不是您完全可以依赖的东西,并且在安装更新后,您应检查系统支持的常规浏览器和其他用户代理是否正常运行。

Chrome 80将于2020年2月或2020年3月过渡到新行为 。 如果您要检查新行为, 可以下载旧版本的Chromium。

如果您无法在2020年初Chrome启用新行为时升级框架版本,则可以将OpenIdConnect流更改为Code流,而不是ASP.NET和ASP.NET Core使用的流。 但这应视为临时措施。


强烈建议您在11月发布.NET Framework和.NET Core的更新版本时,并开始计划更新,然后再对Chrome进行更改。

Source: https://habr.com/ru/post/zh-CN473168/


All Articles