IE 或 Edge Print 对话框在没有会话的情况下向服务器发送请求(因为 SameSite=Lax on session cookie)

Posted

技术标签:

【中文标题】IE 或 Edge Print 对话框在没有会话的情况下向服务器发送请求(因为 SameSite=Lax on session cookie)【英文标题】:IE or Edge Print dialog box send request to server without session (because SameSite=Lax on session cookie) 【发布时间】:2020-03-27 19:34:09 【问题描述】:

我有一个asp.net网站,用户可以登录,会员可以通过Ctrl+P获取报告或打印页面。

最近当我的会员在 IE 中打开我的网站并尝试打印时,他们被注销了!

为什么? 因为 IE 打印对话框在没有会话 cookie 的情况下向服务器发送了一些请求,所以 StateServer 为该客户端释放新会话,然后用户注销。

为什么打印对话框发送请求? 我不知道,但我猜 IE 打印对话框会尝试渲染页面并准备好打印。

为什么打印对话框不发送当前会话 cookie? 因为 .net 的新更新为会话 cookie 设置 SameSite=lax,所以来自打印对话框的请求无法发送当前会话 cookie。 https://support.microsoft.com/en-us/help/4524419/kb4524419

如何防止 IE 打印对话框发送请求? 或者我如何强制 IE 打印对话框发送相同的会话 cookie?

有什么想法吗?

已编辑: 我创建了一个示例项目来展示这个问题。您可以下载我的项目并在 IIS 上托管,然后打开 Default.Aspx 并尝试在 IE(或边缘)中打印该页面。 你会看到我的问题。 https://easyupload.io/w6vvpy

【问题讨论】:

据我所知,使用Ctrl+P打开IE浏览器打印视图时,是浏览器行为,不发送请求就打印当前页面。我建议你可以检查你的代码,是否设置了会话 cookie 过期时间,以及 cookie 是否过期。另外,你用的是哪个版本的IE浏览器?你能发布相关的代码和步骤来重现问题吗? 请在ie(或edgh)中打开此页面,然后打开浏览器开发工具->网络选项卡,然后在页面上按ctrl+P,您会看到一些请求发送到服务器并打印对话框重试渲染页面。 我创建了一个带有表单身份验证的 Web 应用程序,似乎当我在页面上按 ctrl+P 时,它只是从缓存中获取 CSS 和 javascript 文件(或刷新这些文件),并且主页不会新鲜。截图如this。那么,请检查您使用的是哪种身份验证?您使用的是IE浏览器版本吗?您是否正在为 css 和 javascript 文件设置权限,而不是缓存这些文件。此外,请检查 F12 开发者网络工具,确保没有启用“始终从服务器刷新”选项。 @ZhiLv-MSFT:请耐心等待您的回复。我编辑我的帖子并添加一个示例项目。你可以看到我的问题。 【参考方案1】:

我确认这个问题。现在作为一种解决方法,一旦删除 SameSite 属性,问题就会消失。这不是最佳解决方案,但目前似乎可行。

var cookies = this.Response.Cookies;
FormsAuthentication.SetAuthCookie( "JohnDoe", rememberMe );
var allCookies = cookies.AllKeys.Select( key => cookies[key] ).ToList();
allCookies.ForEach( cookie => cookie.SameSite = (SameSiteMode)(-1) );

在 ASP.NET Core 3.0 及更高版本中,SameSite 默认值已更改,以避免与不一致的客户端默认值发生冲突。以下 API 已将默认值从 SameSiteMode.Lax 更改为 -1,以避免为这些 cookie 发出 SameSite 属性

https://docs.microsoft.com/en-us/aspnet/core/security/samesite

我们所做的是,创建了 HttpModule,它在响应中查找 cookie 并相应地修改它们。

【讨论】:

还应设置安全标志。 更多关于 SameSite 行为的信息textslashplain.com/2019/09/30/same-site-cookies-by-default【参考方案2】:

找到解决办法:

您必须在会话状态标记中设置cookieSameSite= "None" 以避免此问题。我已经尝试过了,并且在所有浏览器中都运行良好。

<sessionState cookieSameSite="None" cookieless="false" timeout="360">
</sessionState>

【讨论】:

【参考方案3】:

我已经重现了这个问题,好像我们打印页面的时候,会调用DownloadHandler来加载图片。此时,由于session为null,所以图片不会显示。

为了解决这个问题,我建议您可以尝试使用 QueryString 方法将登录状态传输到 DownloadHandler,而不是使用会话状态。

请尝试修改您的代码如下:

默认.aspx

<img src="" runat="server" id="image" />

默认.aspx.cs

    protected void Page_Load(object sender, EventArgs e)
    
        //check whether user login or not
        if (Session["LoginOK"] != null)
        
            this.Title = "SessionID: " + Session.SessionID;
            //set the image control resource according the session value.
            image.Src = "./DownloadHandler.ashx?LoginOK=" + Session["LoginOK"].ToString();
        
        else
        
            //redirect to the login page 
            //after that, set the session value.
            Session["LoginOK"] = true;
            image.Src = "./DownloadHandler.ashx?LoginOK=true";
        
    

下载处理程序:

        bool.TryParse(context.Request.QueryString["LoginOK"]?.ToString(), out bool hasAccess);

        if (!hasAccess)
        
            context.Response.Redirect("./Error.aspx");
            return;
        

使用上面的代码,当点击打印选项时,它也会向 DownLoadHandler 发送请求,但我们可以根据查询字符串来加载图像。打印网页后,我们仍然可以在主页使用session["LoginOK"](默认)(如果会话未过期)。

【讨论】:

感谢您的回复,但这不是一个好主意,因为它存在安全问题,每个人都可以通过此链接调用我的下载处理程序:./DownloadHandler.ashx?LoginOK=true 您也可以尝试在不使用 DownloadHandler.ashx 的情况下显示图像。为了图片文件的安全,如果不想让匿名用户访问,可以参考this article to set authorization rules for a folder。 这只是一个示例项目,在我的主项目中,DownloadHandler 从数据库加载图像,我无法更改我的方法。

以上是关于IE 或 Edge Print 对话框在没有会话的情况下向服务器发送请求(因为 SameSite=Lax on session cookie)的主要内容,如果未能解决你的问题,请参考以下文章

固定导航菜单在IE 11或Edge中不起作用

选择下拉框不会激活Edge Selenium WebDriver的Edge浏览器上的确认对话框窗口

为什么我不能在IE 11或Edge中的数组元素上调用jQuery方法

Input type="number" - 在 IE11 或 Edge 中不起作用

js 客户端打印html 并且去掉页眉页脚

为啥我的 SVG 在 IE1 或 /Edge 中无法正确显示?