本地调试正常,内网发布后Session变量丢失问题排查
问题描述
本地调试代码时运行完全正常,但部署到内网服务器后出现异常:
- 登录逻辑可正常执行并跳转至Default页面,但Default页面加载时会立刻重定向回登录页
- 约20%概率登录成功,但15-20秒后Session失效,页面再次跳转回登录页
相关代码片段
登录按钮事件(确认无问题)
protected void btnLogin_Click(object sender, EventArgs e) { try { User _user = new User(); _user = _user.SignIn(userName, password); if (_user == null) throw new Exception("Username or password is wrong."); else { Session.Add("User", _user); if (Request["_RDR"] != null) Response.Redirect(Request["_RDR"].ToString()); else Response.Redirect("~/"); } } catch (Exception ex) { lblErrorText.Text = ex.Message; } }
User类的SignIn方法(确认无问题)
public User SignIn(string _username, string _password) { User _user = new User(); Erm_TransferOrderServiceClient client = new Erm_TransferOrderServiceClient(); client.ClientCredentials.Windows.ClientCredential.UserName = _username; client.ClientCredentials.Windows.ClientCredential.Password = _password; CallContext context = new CallContext(); context.Company = "ERH"; try { _user.UserName = _username; _user.Password = _password; string personnelNumber = client.getPersonnelNumber(context); // 仅用于测试连接服务器 } catch (Exception e) { return null; } return _user; }
Default页面Page_Load(问题触发点)
protected void Page_Load(object sender, EventArgs e) { User _user = User.ActiveUser(); if (_user == null) { Response.Redirect("~/Login.aspx"); } else { RefreshGridData(); } }
User类的ActiveUser方法(疑似问题根源)
public static User ActiveUser() { try { var tempUser = HttpContext.Current.Session["User"] as User; User _user = new User(); _user = _user.SignIn(tempUser.UserName, tempUser.Password); return _user; } catch (Exception e) { Console.WriteLine(e); return null; } }
补充测试结果
- 登录页中Session已创建且值正确,但跳转至Default页面后Session变为null
- 约20%概率登录成功,但15-20秒后Session值变为null,页面重定向回登录页
问题分析与解决方案
核心问题定位
内网环境下的Session异常,结合现象来看,主要集中在Session跨页面丢失、应用池异常回收、ActiveUser方法逻辑缺陷三个方面。
1. 服务器Session配置排查
- 检查IIS会话状态设置:
- 单服务器部署时,确认会话状态模式为
InProc;若用StateServer或SQLServer,需确保对应服务正常运行 - 检查会话超时时间,默认20分钟,若被设为15-20秒会直接导致Session快速失效
- 查看应用池的
闲置超时设置,若超时过短会触发应用池回收,清空所有Session
- 单服务器部署时,确认会话状态模式为
- 检查Web.config中的Session配置,确保未手动缩短超时时间:
<sessionState mode="InProc" timeout="20" />
2. Cookie与网络环境问题
- 内网若存在反向代理或负载均衡,需确认Cookie的
Domain和Path设置正确,避免浏览器无法携带SessionId - 若内网未使用HTTPS,需在Web.config中关闭
requireSSL:<httpCookies requireSSL="false" httpOnlyCookies="true" /> - 跳转时可强制指定Session Cookie的域名(按需调整):
Response.Cookies["ASP.NET_SessionId"].Domain = "你的内网域名";
3. ActiveUser方法优化
当前方法存在两个明显缺陷:
- 未判断
tempUser是否为null,若Session丢失会直接抛出异常并返回null - 每次页面加载都调用WCF接口验证,内网环境下WCF连接偶尔失败会触发重定向
优化后的代码:
public static User ActiveUser() { try { var tempUser = HttpContext.Current.Session["User"] as User; if (tempUser == null) { return null; } // 可选:仅在特定场景下重新验证,而非每次页面加载都调用WCF User _user = new User(); _user = _user.SignIn(tempUser.UserName, tempUser.Password); // 验证失败时清空Session if (_user == null) { HttpContext.Current.Session.Remove("User"); } return _user; } catch (Exception e) { // 替换为服务器日志记录,不要用Console.WriteLine // Logger.Error("ActiveUser验证失败", e); HttpContext.Current.Session.Remove("User"); return null; } }
4. 序列化问题
Session存储的对象必须可序列化,否则在内网服务器的应用域切换时无法正确读取。为User类添加序列化特性:
[Serializable] public class User { // 类成员定义 }
调试建议
- 在Default页面的Page_Load中添加日志,输出
Session["User"]是否为null,以及HttpContext.Current.Session.SessionID,对比登录页和Default页的SessionID是否一致 - 查看服务器事件查看器中的应用池回收日志,确认是否是应用池回收导致Session丢失
- 单独测试内网环境下WCF接口
getPersonnelNumber的稳定性,排查是否存在偶尔连接失败的情况
内容的提问来源于stack exchange,提问作者mhmtensyldrm
相关产品推荐
相关产品推荐

