我有一个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(或Edge)中打印该页面。 您会看到我的问题。 https://easyupload.io/w6vvpy
答案 0 :(得分: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并进行相应的修改。
答案 1 :(得分:1)
找到了解决方法:
您必须在会话状态标记中设置cookieSameSite= "None"
,以避免出现此问题。我已经尝试过了,并且在所有浏览器中都能正常工作。
<sessionState cookieSameSite="None" cookieless="false" timeout="360">
</sessionState>
答案 2 :(得分:0)
我已经重现了这个问题,看来当我们打印页面时,它将调用DownloadHandler加载图像。目前,由于会话为null,因此图像将不会显示。
要解决此问题,建议您尝试使用QueryString方法(而不是使用会话状态)将登录状态转移到DownloadHandler。
请尝试如下修改您的代码:
Default.aspx
<img src="" runat="server" id="image" />
Default.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";
}
}
DownloadHandler:
bool.TryParse(context.Request.QueryString["LoginOK"]?.ToString(), out bool hasAccess);
if (!hasAccess)
{
context.Response.Redirect("./Error.aspx");
return;
}
使用上面的代码,当单击打印选项时,它还会向DownLoadHandler发送一个请求,但是我们可以根据查询字符串来加载图像。打印完网页后,我们仍然可以在主页上使用session["LoginOK"]
(默认)(如果会话未过期)。