关于网页关闭的问题!急急急急急急急急急急急急

jinguanghai 2010-11-08 10:29:52
首先每个页面都有关闭功能,关闭又分关闭按钮、网页右上角的X关闭 、alt+F4、点击鼠标右键关闭 数据库里有个表有记录用户登录状态的字段,1为用户已登录,2为用户未登录,我在登陆页面登陆成功以后,把登陆状态2改为1,别人就无法再次登录了(提示用户已登录),如果点击退出按钮,正常退出的时候,可以把已登录状态修改成未登录状态,但是如果用户是用网页右上角的X关闭 、alt+F4、点击鼠标右键关闭的话,就无法修改登录状态了,用户下次登录的时候就会出现用户已登录的提示、我现在的Session存的用户信息,但是不登陆根本就获取不到Session 还有其中我们有个答题页面,只要没有点击提交按钮,无论用任何一种关闭方式,都会把此试卷插入到未完成的试卷表里!请各位高手帮忙看看啊!最好附详细代码与讲解,谢谢各位
...全文
247 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
dengchenlu 2010-11-10
  • 打赏
  • 举报
回复
在web开发时,有的系统要求同一个用户在同一时间只能登录一次,也就是如果一个用户已经登录了,在退出之前如果再次登录的话需要报错


  常见的处理方法是,在用户登录时,判断此用户是否已经在Application中存在,如果存在就报错,不存在的话就加到Application中

(Application是所有Session共有的,整个web应用程序唯一的一个对象):

以下是引用片段:

  string strUserId = txtUser.Text;
  ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;
  if (list == null)
  {
  list = new ArrayList();
  }
  for (int i = 0; i < list.Count; i++)
  {
  if (strUserId == (list[i] as string))
  {
  //已经登录了,提示错误信息
  lblError.Text = "此用户已经登录";
  return;
  }
  }
  list.Add(strUserId);
  Application.Add("GLOBAL_USER_LIST", list);
  当然这里使用Cache等保存也可以。

  接下来就是要在用户退出的时候将此用户从Application中去除,我们可以在Global.asax的Session_End事件中处理:

以下是引用片段:



  void Session_End(object sender, EventArgs e)
  {
  // 在会话结束时运行的代码。
  // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
  // InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
  // 或 SQLServer,则不会引发该事件。
  string strUserId = Session["SESSION_USER"] as string;
  ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;
  if (strUserId != null && list != null)
  {
  list.Remove(strUserId);
  Application.Add("GLOBAL_USER_LIST", list);
  }
  }
这些都没有问题,有问题的就是当用户直接点浏览器右上角的关闭按钮时就有问题了。因为直接关闭的话,并不会立即触发Session过

期事件,也就是关闭浏览器后再来登录就登不进去了。

  这里有两种处理方式:

  1、使用Javascript方式

  在每一个页面中加入一段javascript代码:


以下是引用片段:

  function window.onbeforeunload()
  {
  if (event.clientX>document.body.clientWidth && event.clientY<0||event.altKey){
  window.open("logout.aspx");
  }
  }
  由于onbeforeunload方法在浏览器关闭、刷新、页面调转等情况下都会被执行,所以需要判断是点击了关闭按钮或是按下Alt+F4时才执

行真正的关闭操作。

  然后在logout.aspx的Page_Load中写和Session_End相同的方法,同时在logout.aspx中加入事件:onload="javascript:window.close

()"

  但是这样还是有问题,javascript在不同的浏览器中可能有不同的行为,还有就是当通过文件->关闭时没有判断到。

  2、使用xmlhttp方法(这种方法测试下来没有问题)

  在每个页面中加入如下的javascript(这些javascript也可以写在共通里,每个页面引入就可以了)

以下是引用片段:

  var x=0;
  function myRefresh()
  {
  var httpRequest = new ActiveXObject("microsoft.xmlhttp");
  httpRequest.open("GET", "test.aspx", false);
  httpRequest.send(null);
  x++;
  if(x<60) //60次,也就是Session真正的过期时间是30分钟
  {
  setTimeout("myRefresh()",30*1000); //30秒
  }
  }
  myRefresh();

  在web.config中设置:<sessionState mode="InProc" timeout="1"></sessionState>

  test.aspx页面就是一个空页面,只不过需要在Page_Load中加入:Response.Expires = -1;

  保证不使用缓存,每次都能调用到这个页面。

  原理就是:设置Session的过期时间是一分钟,然后在每个页面上定时每30秒连接一次测试页面,保持Session有效,总共连60次,也就

是30分钟。如果30分钟后用户还没有操作,Session就会过期。当然,如果用户直接关闭浏览器,那么一分钟后Session也会过期。这样就可

以满足要求了。
loadown 2010-11-10
  • 打赏
  • 举报
回复
最保险的是单用户在线模式,后来登陆挤掉先前登陆,不然的话,如果用户因为断电或死机或者浏览器崩溃而导致在线状态不能恢复,就只能等待SESSION过期了。
mark620 2010-11-08
  • 打赏
  • 举报
回复
hwbox 2010-11-08
  • 打赏
  • 举报
回复
还是用ajax心跳保险。
yuxh81 2010-11-08
  • 打赏
  • 举报
回复
aellonxie 2010-11-08
  • 打赏
  • 举报
回复
QQ157636916详谈,你的问题很简单的。。
qh617 2010-11-08
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 csnd88 的回复:]
不太清楚,只说说自己的想法,用户的登录信息不是用session保存的吗,那么不管用户点击退出还是关闭浏览器,session就不是为null了么?也就是说只要保存用户信息的session为null就说明用户是未登录的,我也想不明白,
[/Quote]
同意楼上的
零度的火 2010-11-08
  • 打赏
  • 举报
回复
我建议用JS脚本监控关闭事件,一下函数会监视到你的关闭事件,
然后在WebService()里面自己写调用数据库的代码。

//关闭前刷新List页面
function window.onbeforeunload() {
if (event.clientX > 360 && event.clientY < 0 || (event.altKey)) {
WebService(); //异步调用WebService改写数据库中的字段,这个函数需要自己写
}
}
huluhao 2010-11-08
  • 打赏
  • 举报
回复
补充:是在GOLBLE文件中定义的
huluhao 2010-11-08
  • 打赏
  • 举报
回复
监听session状态嘛...在session销毁的时候退出就是了,就是时效性差,还有在application启动的时候把所有已登陆的用户状态设置为未登陆就可以拉...
csnd88 2010-11-08
  • 打赏
  • 举报
回复
接上,

session["USER"]=session["user"];
if(session["user"]==null)
{
就将session["USER"]保存的用户名的登录状态改为未登录;
将session["USER"]改为null;
}
正常退出的话,只要将session["user"]改为null就可以了,
csnd88 2010-11-08
  • 打赏
  • 举报
回复
不太清楚,只说说自己的想法,用户的登录信息不是用session保存的吗,那么不管用户点击退出还是关闭浏览器,session就不是为null了么?也就是说只要保存用户信息的session为null就说明用户是未登录的,我也想不明白,
jinguanghai 2010-11-08
  • 打赏
  • 举报
回复
请不要发链接,发链接人我是不会给分的!
gongsun 2010-11-08
  • 打赏
  • 举报
回复
web程序中 貌似没有很好的方法去解决这个问题。

-----------------------

你可以用 application 去搞那个在线用户,配置系统定时查询用户状态。

那个未完成的 答卷。 你可以在用户选择 答卷的时候就插入一条 题目的ID,如果用户未提交,关联表中没有数据,则表示未完成。
_LiuHui 2010-11-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 q107770540 的回复:]
http://www.cnblogs.com/hl13571/archive/2008/01/28/1056671.html
[/Quote]

加菲猫。。哇哈哈
q107770540 2010-11-08
  • 打赏
  • 举报
回复
你的这种方法实现单点登陆 很不现实

用户退出的情况有止你想的这的这几种 还有系统强制重启,机器断电等等情况

你可以 换一种思路:

利用session.ID来实现后登陆的人将前边登陆的人T下线
lthaoyue 2010-11-08
  • 打赏
  • 举报
回复
方法1
登录按钮中输入如下代码

private void Button1_Click(object sender, System.EventArgs e)
{
if(TextBox1.Text== "abc " & TextBox2.Text== "abc ")//和数据库验证通过,假设用户名密码均为 "abc "
{
//继续判断是否该用户已经登陆
Hashtable h=(Hashtable)Application[ "Online "];

if(h!=null)
{
//判断哈希表中是否有该用户
IDictionaryEnumerator e1=h.GetEnumerator();
bool flag=false;
while(e1.MoveNext())
{
if(e1.Value.ToString()== "abc ")
{
flag=true;
break;
}
}
if(flag) //已经登陆
{
Label1.Text= "Login already! ";
return;
}
}
else
{
h=new Hashtable();
}

//保存用户到Application中
h[Session.SessionID]= "abc ";
Application[ "Online "]=h;
}
else
{
TextBox1.Text= " ";
TextBox2.Text= " ";
Label1.Text= "User/Password failed! ";
return;
}
}

Global.asax文件中改写方法

protected void Session_End(Object sender, EventArgs e)
{
Hashtable h=(Hashtable)Application[ "Online "];

if(h[Session.SessionID]!=null)
h.Remove(Session.SessionID);

Application[ "Online "]=h;
}

方法2
由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录。在ASP.NET中实现单点登录其实很简单,下面就把主要的方法和全部代码进行分析。

实现思路

利用Cache的功能,我们把用户的登录信息保存在Cache中,并设置过期时间为Session失效的时间,因此,一旦Session失效,我们的Cache也过期;而Cache对所有的用户都可以访问,因此,用它保存用户信息比数据库来得方便。

SingleLogin.aspx.cs代码

usingSystem;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Web;
usingSystem.Web.SessionState;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.HtmlControls;

namespaceeMeng.Exam
{
///
///SingleLogin的摘要说明。
///实现单点登录
///
publicclassSingleLogin:System.Web.UI.Page
{
protectedSystem.Web.UI.WebControls.TextBoxUserName;
protectedSystem.Web.UI.WebControls.TextBoxPassWord;
protectedSystem.Web.UI.WebControls.LabelMsg;
protectedSystem.Web.UI.WebControls.ButtonLogin;

privatevoidPage_Load(objectsender,System.EventArgse)
{
//实际例子可访问:
//http://dotnet.aspx.cc/Exam/SingleLogin.aspx
}

#regionWeb窗体设计器生成的代码
overrideprotectedvoidOnInit(EventArgse)
{
InitializeComponent();
base.OnInit(e);
}

///
///设计器支持所需的方法-不要使用代码编辑器修改
///此方法的内容。
///
privatevoidInitializeComponent()
{
this.Login.Click+=newSystem.EventHandler(this.Login_Click);
this.Load+=newSystem.EventHandler(this.Page_Load);
}
#endregion

privatevoidLogin_Click(objectsender,System.EventArgse)
{
//作为唯一标识的Key,应该是唯一的,这可根据需要自己设定规则。
//做为测试,这里用用户名和密码的组合来做标识;也不进行其它的错误检查。

//生成Key
stringsKey=UserName.Text+ "_ "+PassWord.Text;
//得到Cache中的给定Key的值
stringsUser=Convert.ToString(Cache[sKey]);
//检查是否存在
if(sUser==null||sUser==String.Empty)
{
//Cache中没有该Key的项目,表名用户没有登录,或者已经登录超时
//注意下面使用的TimeSpan构造函数重载版本的方法,是进行是否登录判断的关键。
TimeSpanSessTimeOut=newTimeSpan(0,0,System.Web.HttpContext.Current.Session.Timeout,0,0);
HttpContext.Current.Cache.Insert(sKey,sKey,null,DateTime.MaxValue,SessTimeOut,
System.Web.Caching.CacheItemPriority.NotRemovable,null);
Session[ "User "]=sKey;
//首次登录,您可以做您想做的工作了。
Msg.Text= "嗨!欢迎您访问【孟宪会之精彩世界】 ";
Msg.Text+= ",祝您浏览愉快!:)
";
}
else
{
//在Cache中发现该用户的记录,表名已经登录过,禁止再次登录
Msg.Text= "抱歉,您好像已经登录了呀:-(
";
return;
}
}
}
}
摘自:http://topic.csdn.net/t/20051228/12/4486044.html
加载更多回复(3)

62,052

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧