今天的干货长驱直入, 直奔主题
看了前文的同学们应该都知道, 搜狗, 360 等浏览器在单点登录中反复重定向, 最终失败报错.
原因在于, 非 Chrome80 + 浏览器不识别 Cookie 上的 SameSite=none 属性值, 导致认证 Cookie 在后续请求中被抛弃.
截至 2020/3/30 号, 非 Chrome 浏览器测试包含两种结果:
case1: 可设置 cookie 的 samesite=none, 浏览器可读取该 cookie
case2: 对 cookie 设置 samesite=none, 浏览器不能读取该 cokie
浏览器 | 最新版本号 | 结果 | 备注 |
---|---|---|---|
IE | 11 | case1 | win10 |
Edge | 44.18362.449.0 | case1 | 2020/2/15 开始使用 chrome 内核 / 70.0.3538.102 |
Firefox | 74 | case1 | |
360 急速浏览器 | 12.0.1190.0 | case1 | 基于 chromium78 |
搜狗浏览器 | 8.6.1.31812 | case2 | User-Agent: Chrome/65.0.3314.0 |
猎豹安全浏览器 | 6.5.115 | case2 | User-Agent:Chrome/57.0.2987.98 |
QQ 浏览器 | 10.5.3 | case1 | chromium 70 |
华为手机浏览器 | 10.0.6.304 | case1 | |
魅族手机浏览器 | 8.5.1 | case2 |
嗯, 我之前报的 360 急速浏览器在新版已经更新了 Chrome 内核, 作为主流的搜狗和猎豹浏览器还是使用旧版本 Chrome 内核, 这是要闹哪样?
如果 web 应用程序打算支持旧内核浏览器, 则需要实现浏览器嗅探.
ASP.NET Core 不会帮你实现浏览器嗅探, 因为 User-Agents 值易变且经常更改.
但是 Microsoft.AspNetCore.CookiePolicy 中的扩展点允许插入浏览器嗅探逻辑.
在 Startup.Configure 中, 在调用 UseAuthentication 或任何写入 cookie 的方法之前添加调用 UseCookiePolicy 的代码:
- public void Configure(IApplicationBuilder App, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- else
- {
- App.UseExceptionHandler("/Error");
- App.UseHsts();
- }
- App.UseHttpsRedirection();
- App.UseStaticFiles();
- App.UseRouting();
- // 表示 ASP.NET Core 启动 Cookie 策略
- App.UseCookiePolicy();
- App.UseAuthentication();
- App.UseAuthorization();
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapRazorPages();
- });
- }
在 Startup.ConfigureServices, 添加 Cookie 的策略配置代码:
- public void ConfigureServices(IServiceCollection services)
- {
- services.Configure<CookiePolicyOptions>(options =>
- {
- options.MinimumSameSitePolicy = (SameSiteMode)(-1);
- options.OnAppendCookie = cookieContext =>
- CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
- options.OnDeleteCookie = cookieContext =>
- CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
- });
- services.AddRazorPages();
- }
- private void CheckSameSite(HttpContext httpContext, CookieOptions options)
- {
- if (options.SameSite == SameSiteMode.None)
- {
- var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
- if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
- {
- options.SameSite = SameSiteMode.Unspecified;
- }
- }
- }
上面的例子中, MyUserAgentDetectionLib.DisallowsSameSiteNone 是一个自定义的库文件, 侦测不支持 SameSite=None 的 UserAgent.
ASP.NET Core3.1 对与 SameSiteMode 新增了一个 Unspecified 枚举值, 表示服务端不会对 Cookie 设置 SameSite 属性值, 后面的携带 Cookie 的事情交给浏览器默认配置.
具体的侦测代码如下:
- public static bool DisallowsSameSiteNone(string userAgent)
- {
- // Check if a null or empty string has been passed in, since this
- // will cause further interrogation of the useragent to fail.
- if (String.IsNullOrWhiteSpace(userAgent))
- return false;
- // 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.
- 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.
- if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
- userAgent.Contains("Version/") && userAgent.Contains("Safari"))
- {
- 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.
- if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
- {
- return true;
- }
- return false;
- }
总结
本文实战演示在 ASP.NET Core 扩展点插入浏览器嗅探逻辑, 解决设备不支持 cookie SameSite=none 的历史问题.
来源: https://www.cnblogs.com/JulianHuang/p/12596115.html