首先,好消息是Google将于2020年2月份发布Chrome 80版本。本次发布将推进Google的“渐进改良Cookie”策略,打造一个更为安全和保障用户隐私的网络环境。

坏消息是,本次更新可能导致浏览器无法向服务端发送Cookie。如果你有多个不同域名的应用,部分用户很有可能出现会话时常被打断的情况,还有部分用户可能无法正常登出系统。

本篇博客将处理第一个问题(无法发送cookie到服务端)。至于第二个问题(cookie无法被删除),请参考另一篇博客

首先,SameSite是什么

互联网是十分开放的平台:Cookie诞生于二十多年前,于2011年修订(RFC 6265)。当时跨站访问攻击(CSRF)没有现在这么猖獗,侵犯用户隐私的行为也不像现在这样泛滥。

简而言之,Cookie标准规范规定,如果某域名下设置了Cookie,不管你是直接跳转到该域名,或是加载了该域名的某些资源(例如图片),或是向该域名发送POST请求,亦或将其嵌入iframe,浏览器访问该域名的每次请求,都将带上这个Cookie。

对于iframe嵌入的场景,你可能不希望浏览器将用户会话cookie自动发送到服务器,因为这样任何其他网站都可以在用户不知情的情况下,用他的会话上下文,跟你的服务器发送请求。

为了避免这种情况,SameSite cookie规范于2016年起草。对于发送cookie我们有了更多的控制权:现在可以明确指定每个cookie是否被发送。规范引入了同站/跨站cookie的概念,如果浏览器访问A域名,请求服务端也是A域名,这些cookie就叫同站cookies(same-site cookies),如果浏览器访问A域名,请求服务端是B域名,这些cookie就叫跨站cookies(cross-site cookies)。

为了向后兼容,same-site的默认设置并未改变之前的行为。你必须手动指定SameSite=Lax或者SameSite=Strict,来能使用这项特性加固安全。所有的.NET框架和常见的浏览器都已支持这一特性。设置为Lax,大多数情况不允许发送第三方Cookie,导航到目标网址的Get请求除外。设置为Strict,完全禁止第三方Cookie,除非你之前访问过该域名而Cookie已经存在于浏览器。

悲哀的是,这项新特性的采用率低的可怜(基于Chrome2019年3月份统计显示,在所有的cookie中,只有0.1%使用了SameSite标志)。

Google决定推进这项特性的使用。他们决定修改世界上最多人使用的浏览器——Chrome的默认设置:如果想保持之前处理cookie的方式,Chrome 80要求显示指定SameSite=None。如果像以前一样忽略SameSite属性,Chrome将视作SameSite=Lax。

请注意:SameSite=None只有在Cookie同时被标记为Secure并且使用https连接时才会生效。

更新:如果你想知道关于SameSite cookies的更多背景知识,请扩展阅读这篇文章

这会影响我吗?什么影响?

如果你有一个单页应用(SPA),使用另一域名的认证服务(比如IdentityServer4)进行身份认证,并且使用了所谓的静默令牌刷新的话,你将受影响。

译者注:使用refresh_token刷新access_token,用户无感知

登录到认证服务的时候,它会为当前用户设置会话cookie,这个cookie属于认证服务域名。认证流程结束之后,另一域名会收到认证服务颁发的access token,有效期通常不会太长。当access token过期之后,应用无法访问api,用户需要频繁的登录,体验十分差。

为了避免这一情况,我们可以使用refresh_token实现静默刷新。应用创建一个用户不可见的iframe,在iframe中进行新的认证流程。iframe中加载了认证服务站点,当浏览器发送会话cookie的时候,认证服务识别出当前用户然后颁发新的token。

SPA网站使用iframe嵌入了认证服务站点的内容,这就是一个跨站请求,只有将iframe中属于认证服务站点的cookie设置为SameSite=None,Chrome 80才会将iframe中的cookie发送到认证服务。否则,token静默刷新将无法正常运行。

可能还会导致一些其他的问题:如果应用中嵌入了其他域名的资源,比如视频自动播放设置,它们需要cookie才能正常运行。某些依赖cookie认证来访问第三方API的应用也会出现问题。

注意:很显然你只能修改自己服务的cookie设置。如果使用了其他域名的资源,这些不在你的控制范围之内,你需要联系第三方修改他们的cookie设置。

好的,我会修改代码将SameSite设置为None的,这样就万事大吉了,是吗?

很不幸,并不是:Safari存在一个"bug"。这个bug导致Safari不会将None识别为SameSite的合法值。当Safari遇到非法参数值的时候,它会将其视作SameSite=Strict,不会向认证服务发送会话cookie。IOS13和macOS 10.15 Catalina系统上的Safari 13已修复此bug,macOS 10.14 Mojave和iOS 12将不会修复,而这几个版本依旧存在大量用户群。

现在我们进退两难:要么忽略此次更新,Chrome用户无法使用静默刷新,要么设置SameSite=None,那么无法更新到最新系统的iPhone,iPad和Mac用户的应用将出现异常。

有没有方法明确知道自己受影响?

幸运的是,你可以。如果你已经设置了SameSite=None,应该注意到应用在iOS 12,macOS 10.4的Safari上运行异常。如果还没有设置的话,确保要在上面版本系统的Safari上做一下测试。

如果还没有设置的话,可以打开Chrome的开发者工具。可以看到这些警告:

A cookie associated with a cross-site resource at {cookie domain} was set without the `SameSite` attribute.
A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`.
You can review cookies in developer tools under Application>Storage>Cookies and see more details at
https://www.chromestatus.com/feature/5088147346030592 and
https://www.chromestatus.com/feature/5633521622188032.

如果设置了SameSite=None但是没有Secure标识,将看到如下警告:

A cookie associated with a resource at {cookie domain} was set with `SameSite=None` but without `Secure`.
A future release of Chrome will only deliver cookies marked `SameSite=None` if they are also marked `Secure`.
You can review cookies in developer tools under Application>Storage>Cookies and
see more details at https://www.chromestatus.com/feature/5633521622188032.

怎样才能修复这个问题?我需要Chrome和Safari都能正常运行。

我和我的同事Boris Wilhelms做了一些研究和验证,找到了一个解决方案。微软的Barry Dorrans写了一篇很不错的博客可以参考。这个解决方案并不是完美之策,它需要在服务端嗅探浏览器类型,但是它很简单,在过去几周,我们已经用这个方案修复了数个项目。

首先我们需要确保需要通过跨站请求发送的cookie - 比如会话cookie - 被设置为SameSite=None并且标识为Secure。我们需要在项目中找到Cookie选项配置代码,然后做出调整。这样Chrome的问题修复了,然后Safari会出现问题。

然后我们需要将下面的类和代码段加到项目中。这段代码在ASP.NET Core应用中配置了一个cookie策略。这个策略会检查cookie是否应该被设置位SameSite=None。

请注意:这个解决方案是.NET Core使用的。至于.NET Framework项目,请查看Barry Dorran的这篇博客

将这个类加到项目中

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; namespace Microsoft.Extensions.DependencyInjection
{
public static class SameSiteCookiesServiceCollectionExtensions
{
/// <summary>
/// -1 defines the unspecified value, which tells ASPNET Core to NOT
/// send the SameSite attribute. With ASPNET Core 3.1 the
/// <seealso cref="SameSiteMode" /> enum will have a definition for
/// Unspecified.
/// </summary>
private const SameSiteMode Unspecified = (SameSiteMode) (-1); /// <summary>
/// Configures a cookie policy to properly set the SameSite attribute
/// for Browsers that handle unknown values as Strict. Ensure that you
/// add the <seealso cref="Microsoft.AspNetCore.CookiePolicy.CookiePolicyMiddleware" />
/// into the pipeline before sending any cookies!
/// </summary>
/// <remarks>
/// Minimum ASPNET Core Version required for this code:
/// - 2.1.14
/// - 2.2.8
/// - 3.0.1
/// - 3.1.0-preview1
/// Starting with version 80 of Chrome (to be released in February 2020)
/// cookies with NO SameSite attribute are treated as SameSite=Lax.
/// In order to always get the cookies send they need to be set to
/// SameSite=None. But since the current standard only defines Lax and
/// Strict as valid values there are some browsers that treat invalid
/// values as SameSite=Strict. We therefore need to check the browser
/// and either send SameSite=None or prevent the sending of SameSite=None.
/// Relevant links:
/// - https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1
/// - https://tools.ietf.org/html/draft-west-cookie-incrementalism-00
/// - https://www.chromium.org/updates/same-site
/// - https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
/// - https://bugs.webkit.org/show_bug.cgi?id=198181
/// </remarks>
/// <param name="services">The service collection to register <see cref="CookiePolicyOptions" /> into.</param>
/// <returns>The modified <see cref="IServiceCollection" />.</returns>
public static IServiceCollection ConfigureNonBreakingSameSiteCookies(this IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
}); return services;
} private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); if (DisallowsSameSiteNone(userAgent))
{
options.SameSite = Unspecified;
}
}
} /// <summary>
/// Checks if the UserAgent is known to interpret an unknown value as Strict.
/// For those the <see cref="CookieOptions.SameSite" /> property should be
/// set to <see cref="Unspecified" />.
/// </summary>
/// <remarks>
/// This code is taken from Microsoft:
/// https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
/// </remarks>
/// <param name="userAgent">The user agent string to check.</param>
/// <returns>Whether the specified user agent (browser) accepts SameSite=None or not.</returns>
private static bool DisallowsSameSiteNone(string userAgent)
{
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the
// iOS networking stack.
// Notes from Thinktecture:
// Regarding https://caniuse.com/#search=samesite iOS versions lower
// than 12 are not supporting SameSite at all. Starting with version 13
// unknown values are NOT treated as strict anymore. Therefore we only
// need to check version 12.
if (userAgent.Contains("CPU iPhone OS 12")
|| userAgent.Contains("iPad; CPU OS 12"))
{
return true;
} // Cover Mac OS X based browsers that use the Mac OS networking stack.
// This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// because they do not use the Mac OS networking stack.
// Notes from Thinktecture:
// Regarding https://caniuse.com/#search=samesite MacOS X versions lower
// than 10.14 are not supporting SameSite at all. Starting with version
// 10.15 unknown values are NOT treated as strict anymore. Therefore we
// only need to check version 10.14.
if (userAgent.Contains("Safari")
&& userAgent.Contains("Macintosh; Intel Mac OS X 10_14")
&& userAgent.Contains("Version/"))
{
return true;
} // Cover Chrome 50-69, because some versions are broken by SameSite=None
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
// Notes from Thinktecture:
// We can not validate this assumption, but we trust Microsofts
// evaluation. And overall not sending a SameSite value equals to the same
// behavior as SameSite=None for these old versions anyways.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
} return false;
}
}
}

配置并启用cookie策略

在Starup中加入下面的代码,使用cookie策略

public void ConfigureServices(IServiceCollection services)
{
// Add this
services.ConfigureNonBreakingSameSiteCookies();
} public void Configure(IApplicationBuilder app)
{
// Add this before any other middleware that might write cookies
app.UseCookiePolicy(); // This will write cookies, so make sure it's after the cookie policy
app.UseAuthentication();
}

Ok,完事了吗?

还需要做全面的测试,特别是Chrome79,以及受影响的Safari版本。

检查一下你的静默token刷新,还有需要cookie的跨站请求,是否正常工作。

这些都没问题就完事了。

可以等IdentityServer4修复这个问题吗?

不太可能。并不是IdentityServer在管理这些cookie。IdentityServer依赖于ASP.NET Core框架内置的认证系统,它们在管理会话cookie。然而微软表示它们不能使用在ASP.NET Core直接嗅探浏览器版本的方案。所以基本上短期内只能靠自己了。

总结

Chrome于2020年2月发布的新版本修改了cookie的默认行为。新版本需要SameSite明确设置为None,同时有Secure标识,才会将该cookie发送到跨站请求。如果你这么做的话,很多版本的Safari会出现问题。

为了确保应用在所有浏览器运行正常,我们将所有受影响的cookie设置为Secure,SameSite=None,然后新增一个Cookie策略,根据浏览器版本动态处理SameSite设置。

译者注

文中提到的方案需要设置SameSiteMode=-1,这个新增加的枚举,需要更新微软相补丁包,.net core2.1由于是长期维护版本微软提供了补丁包,.net core 3.x也已经支持。如果是2.2或者其他不再维护的版本,可能需要升级到3.x。详情见下面的博客。

https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

如果因为各种原因无法升级.net core,可以使用nginx反向代理,加入如下配置即可。

这个方案只能解决Chrome,放弃掉Safari部分版本的兼容性。(本人用的这种方式)

proxy_cookie_path / "/; httponly; secure; SameSite=None;";

如果希望Chrome和Safari兼顾,可以安装ngx_http_js_module模块,让nginx嗅探浏览器,动态去设置SameSite,参考

https://blog.csdn.net/tmyth/article/details/104340403

http://nginx.org/en/docs/http/ngx_http_js_module.html


原文地址:https://www.thinktecture.com/en/identity/samesite/prepare-your-identityserver/

Chrome80调整SameSite策略对IdentityServer4的影响以及处理方案(翻译)的更多相关文章

  1. 【Shared Server Mode】测试调整shared_servers参数对数据库的影响

    本文来源于:secooler  的 <[Shared Server Mode]测试调整shared_servers参数对数据库的影响> 关于Shared Server模式的配置方法请参见文 ...

  2. 谷歌SameSite策略

    当我新下载谷歌80.x版本的时候,访问一个系统(内嵌跳转到其他系统的iframe),跳转过去没有携带cookie,以前版本的谷歌浏览器是可以的,控制台提示SameSite策略,给阻止了cookie携带 ...

  3. Chrome升级到91版本以上后Cookies SameSite问题,IdentityServer4登录不上问题?

    还原下问题: 跨站Cookie安全级别限制,如过是https不用担心这个问题,但是IP访问,本地测试等就会出现登录不上 针对这个问题,记得早在之前80版本的chrome就会存在的问题,可能大家会用:c ...

  4. IdentityServer4之Jwt身份验证方案分析

    一,准备内容 在之前讲过的asp.net core 实现OAuth2.0四种模式系列中的IdentityApi客户端用到了以下配置代码 public void ConfigureServices(IS ...

  5. IdentityServer4系列 | 简化模式

    一.前言 从上一篇关于资源密码凭证模式中,通过使用client_id和client_secret以及用户名密码通过应用Client(客户端)直接获取,从而请求获取受保护的资源,但是这种方式存在clie ...

  6. Dell服务器Raid卡电池策略调整

    DELL服务器的Riad卡都有可充电池的特性,这块可充电电池,在不使用时,也会有微弱的放电现象,当它的电量放电到低到一定程度时,Raid卡控制器就会对电池进行一次“放电”,将剩余的电量放掉,然后再进行 ...

  7. IdentityServer4迁移至3.x版本注意问题详解

    前言 之前有一位购买我课程的童鞋利用最新的IdentityServer4版本即对应.NET Core 3.x,发布到生产环境在学习,结果出了一些问题,此前我并未过多关注IdentityServer4升 ...

  8. 关于网站高性能中磁盘cpu以及内存对网站性能的影响

    之前和同事聊天的时候,提到了这个硬件方面(包括内存,cpu,以及硬盘的存储选择),个人认为可以从这几个方面来提高底层硬件的性能,从而提高网站的整体吞吐量和速度. 一.主机: (1).CPU:决定处理的 ...

  9. Oracle 优化和性能调整

    分析评价Oracle数据库性能主要有数据库吞吐量.数据库用户响应时间两项指标.数据库用户响应时间又可以分为系统服务时间和用户等待时间两项,即:  数据库用户响应时间=系统服务时间+用户等待时间  因此 ...

随机推荐

  1. ButterKnife的使用及其解析

    本博客介绍ButterKnife的使用及其源码解析. ButterKnife的使用 ButterKnife简介 添加依赖 在Project级别的build.gradle文件中添加为ButterKnif ...

  2. C#面向对象--属性

    一.属性(Property)作为类和结构的成员,是对字段的一种封装方式,实际上是一种特殊的方法,被称为访问器(Accessor),从而隐藏实现和验证代码,有助于提高字段读取和赋值的安全性和灵活性: 1 ...

  3. hw从外网到内网的渗透姿势分享

    现在这段时间是全员 hw 时期,刚好前几天也有幸参与了某个地方的 hw 行动,作为攻击方,这里就简单总结一下最近挖洞的思路吧.因为可能怕涉及到敏感的东西,这里就有的地方不会细说了. 因为本人比较菜,所 ...

  4. MySQL root密码重置问题

    1:进入cmd,停止mysql服务:Net stop mysql (进入服务---->MySql----->停止) 到mysql的安装路径启动mysql,在bin目录下使用mysqld-n ...

  5. paddlepaddle目标检测之水果检测(yolov3_mobilenet_v1)

    一.创建项目 (1)进入到https://aistudio.baidu.com/aistudio/projectoverview/public (2)创建项目 点击添加数据集:找到这两个 然后创建即可 ...

  6. k8s环境部署.net core web项目(docker本地仓库)

    在之前的文档中,我们部署了.net core web在k8s环境下,达成了集群管理项目的目的.但是,由于是本地部署,需要在所有的node节点都拉取好镜像,这是非常麻烦的,为了只维护一份代码,同步更新. ...

  7. [续更]一起来撸一下Flex布局里面的那些属性

    Flex的全称是Flexible Box,意为弹性布局,用来为盒模型提供最大的灵活性. Flex包含的属性有很多,每个属性又包含了许多不同意义的属性值···然而在实际开发中,能被我们临幸的可能也只是那 ...

  8. canvas初尝试

    最近学习了canvas,就拿它做了这么个小东西,感觉已经爱上canvas了.上代码 /* * @auhor : 开发部-前端组-李鑫超 * @property { tableData : {Array ...

  9. Error response:/usr/bin/tf_serving_entrypoint.sh: line 3: 6 Illegal instruction (core dumped) ...

    用docker部署tensorflow-serving:gpu时,参照官方文档:https://tensorflow.google.cn/tfx/serving/docker 本应该是很简单的部署,没 ...

  10. ABP开发框架前后端开发系列---(16)ABP框架升级最新版本的经验总结

    有一小段时间没有持续升级ABP框架了,最近就因应客户的需要,把ABP框架进行全面的更新,由于我们应用的ABP框架,基础部分还是会使用官方的内容,因此升级的时候需要把官方基础ABP的DLL进行全面的更新 ...