ASP.net 实现禁止用户重复登录
本文先为大家介绍如何利用缓存Cache方便地实现此功能。
Cache与Session这二个状态对像的其中有一个不同之处,Cache是一个全局对象,作用的范围是整个应用程序,所有用户;
而Session是一个用户会话对象,是局部对象,用于保存单个用户的信息。
只要把每次用户登录后的用户信息存储在Cache中,把Cache的Key名设为用户的登录名,Cache的过期时间设置为Session的超时时间,在用户每次登录的时候去判断一下Cache[用户名]是否有值,如果没有值,证明该用户没有登录,否则该用户已登录。
为大家举一个例子吧。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/// <summary>/// 防止多次登录/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Button1_Click(object sender, System.EventArgs e){string strUser = string.Empty;string strCacheKey = this.TextBox1.Text;strUser = Convert.ToString(Cache[strCacheKey]);if (strUser == string.Empty){TimeSpan SessTimeOut = new TimeSpan(0, 0, System.Web.HttpContext.Current.Session.Timeout, 0, 0);Cache.Insert(strCacheKey, strCacheKey, null, DateTime.MaxValue, SessTimeOut, CacheItemPriority.NotRemovable, null);Session["User"] = strCacheKey;this.Label1.Text = Session["User"].ToString();}else{this.Label1.Text = "这个用户已经登录!";}} |
在网上又找了下,发现了另外两种解决方案:
1、通过数据库状态位判断该用户是否已经登录。
2、利用session监听器监听每一个登录用户的登录情况。
第一种解决方案很简单,但需要考虑用户非正常退出的情况,如直接关闭浏览器等等,可用性较低。
接下来,主要介绍第二种方案的具体实现:利用session监听器监听每一个登录用户的登录情况。
A.用户登录后,先去数据库查询该登录名是否存在、是否锁定,在登录名存在且非锁定的情况下,从application内置作用域对象中取出所有的登录信息,查看该登录名是否已经登录,如果登录了,就友好提示下;反之表示可以登录,将该登录信息保存在application中。
主要代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
////所有的登录信息Map<String, String> loginUserMap = (Map<String, String>) super.getApplicationAttr(Constant.LOGIN_USER_MAP);boolean isExist = false;String sessionId = super.getSessionId(false);if(loginUserMap==null){loginUserMap = new HashMap<String, String>();}for (String username : loginUserMap.keySet()) {//判断是否已经保存该登录用户的信息,是否为同一个用户进行重复登录if(!username.equals(user.getFuUserName()) || loginUserMap.containsValue(sessionId)){continue;}isExist = true;break;}if(isExist){//该用户已登录//}else {//该用户没有登录loginUserMap.put(result.getFuUserName(), sessionId);//}// |
B.登录考虑完之后,来考虑考虑退出。
用户正常退出时,我们需要将该用户的登录信息从session中移除。我们可以写一个Session监听器,监听sessioon销毁的时候,我们将登录的用户注销掉,也就是从application中移除。表示该用户已经下线了。
主要代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//public void sessionDestroyed(HttpSessionEvent event) { // //在session销毁的时候 把loginUserMap中保存的键值对清除 User user = (User)event.getSession().getAttribute("loginUser"); if(user!=null){ Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute("loginUserMap"); loginUserMap.remove(user.getFuUserName()); event.getSession().getServletContext().setAttribute("loginUserMap",loginUserMap); } //} // |
另外,还有一个问题,如果说登录的用户突然关闭了浏览器而没有点击退出按钮。那么可以利用beforeunload 事件,在浏览器刷新或者关闭的时候触发。
|
1
2
3
4
5
6
7
8
9
10
|
//在刷新或关闭时调用的事件$(window).bind('beforeunload',function(){ $.ajax({ url:"${ctx}/system/user/user!logout.action", type:"post", success:function(){ alert("您已退出登录"); } });}); |
这样基本就实现了需求。
大家可以把上面代码运用到自己的项目中,检测一下,有效的防止同一账号的重复登录,希望大家喜欢这些方法。
ASP.net 实现禁止用户重复登录(踢出先登录的)
应客户要求,须在系统中实现禁止用户重复登录。
我采用的是asp.net自带的登录组件,有很多现成属性和方法可用,比如,Membershipuser.Comment可用来存储用户的特定登录信息,本例中的时间刻录,就存储在这个属性中。注意,存储后,记得用Membership.UpdateUser 方法来保存信息。
如果没有采用asp.net自带的登录组件,则可通过Application或数据库来保存,其原理是一样的。
为了解决用户提出的“禁止同一用户名重复登录”的要求,曾经采用更两种解决方案。
最初采用的方案,是利用MembershipUser.IsOnline 来判断用户是否在线,如果在线,则禁止登录。
If sUser.IsOnline Then
Me.CustomValidator1.ErrorMessage = "该用户已经在另一地点登录!"
args.IsValid = False
Exit Sub
End If
但是,这一方案有一缺点,当用户非正常退出时,由于Session值的消失要20分钟左右,因此在这20分钟内,系统无法判断客户端是否已经退出,只能作为用户仍然在线来对待。也就是说,这20分钟内,该用户无法再次登录,必须等20分钟后,方可正常登录。
这样明显无法满足客户要求。所以,后来我就采用了第二种方案:后登录的用户,踢出先登录的用户。
第二种方案的实现原理如下:
1.登录时在User.Comment中保存登录的时间刻度,同时在Session中保存同一刻度数。代码如下:
If Membership.ValidateUser(sUserName, sPassword) Then
Dim sLoginTicks As String = Now.Ticks.ToString
sUser.Comment = sLoginTicks
Membership.UpdateUser(sUser) '保存到User.comment值中
Page.Session.Add("LoginTicks", sLoginTicks) '保存到Session中
FormsAuthentication.SetAuthCookie(sUserName, False)
Response.Redirect("Default.aspx")
Else
Response.Write("<script> alert(""用户名或密码错误!"");location.href = """ & Request.Url.ToString & """;</script>")
Response.End()
End If
2.在页面登录验证时,对比Session中时间刻度,和User.comment中的时间刻度是否相同。后登录的,这两个值同时被更新,必定会相同。而先登录的用户,由于Session中的值未更新,而User.comment中的值,被后登录的用户更新掉了,因此值不同,从而被踢出。代码如下:
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Dim HomePage As String = Me.ResolveUrl("~/Default.aspx")
If Page.Request.IsAuthenticated = True Then '本句用来验证是否登录
Dim sUser As MembershipUser = Membership.GetUser
If Page.Session("LoginTicks") IsNot Nothing Then
If Me.Page.Session("LoginTicks").ToString <> sUser.Comment.ToString Then
FormsAuthentication.SignOut()
Response.Write("<script> alert(""相同帐号在其它地点登录,你被迫注销。如有疑问,请与网站管理员联系。"");location.href = """ & HomePage & """;</script>")
Response.End()
End If
End If
End If
End Sub
经测试,该方案完美解决了禁止用户重复登录的问题
二、
实现思路:
用户登录成功后,将用户登录信息存放到Hashtable类型的Application["Online"]里面,其键值为SessionID,其Value值为用户ID;当用户注销时,调用Session.Abandon;在Global.asax里面的SessionEnd事件中,将用户ID从Hashtable中删除;在用户访问页面时,察看Hashtable中是否有对应的用户ID如果没有则判断用户不在线(用户不在线的原因可能是按了注销按钮、网页超时等)
1、公用类中判断用户是否在线的函数(供用户调用)
Code
/**//// <summary>
/// 判断用户strUserID是否包含在Hashtable h中
/// </summary>
/// <param name="strUserID"></param>
/// <param name="h"></param>
/// <returns></returns>
public static bool AmIOnline(string strUserID, Hashtable h)
{
if (strUserID == null)
return false;
//继续判断是否该用户已经登陆
if (h == null)
return false;
//判断哈希表中是否有该用户
IDictionaryEnumerator e1 = h.GetEnumerator();
bool flag = false;
while (e1.MoveNext())
{
if (e1.Value.ToString().CompareTo(strUserID) == 0)
{
flag = true;
break;
}
}
return flag;
}
2、用户登录事件处理:
Code
private void btnlogin_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
//User为自定义的类,其中包含Login方法
User CurUser = new User();
CurUser.UserID = this.username.Text.Trim();
if (MyUtility.AmIOnline(CurUser.UserID, (Hashtable) Application["Online"]))
{
JScript.Alert("您所使用的登录ID已经在线了!您不能重复登录!");
return;
}
CurUser.LoginPsw = FormsAuthentication.HashPasswordForStoringInConfigFile(this.password.Text.Trim(), "SHA1");
int ii = CurUser.Login();
StringBuilder sbPmt = new StringBuilder();
switch (ii)
{
case 0: //如果登录成功,则将UserID加入Application["Online"]中
Hashtable h = (Hashtable) Application["Online"];
if (h == null)
h = new Hashtable();
h[Session.SessionID] = CurUser.UserID;
Application["Online"] = h;
Session["UserID"] = CurUser.UserID;
Session["UserNM"] = CurUser.UserNM;
Session["RoleMap"] = CurUser.RoleMap;
Session["LoginPsw"] = CurUser.LoginPsw;
Session["LoginTime"] = DateTime.Now;
Response.Redirect("ChooseRole.aspx");
break;
case -1:
JScript.Alert("用户名错误!");
break;
case -2:
JScript.Alert("密码错误!");
break;
default:
sbPmt.Append("登录过程中发生未知错误!");
JScript.Alert(sbPmt.ToString());
break;
}
return;
}
3、在Global.asax中的Session_End事件:
Code
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;
}
4、在每一个页面需要刷新的地方,调用如下代码:
Code
try
{
if (!common.MyUtility.AmIOnline(Session["UserID"].ToString(), (Hashtable) Application["OnLine"]))
{
//用户没有在线 ,转到登录界面
Response.Write("<script>parent.document.location.href='Login.aspx';</script>"); ////有框架时用
//Response.Redirect("login.aspx"); ////无框架时用
return;
}
}
catch
{
//会话过期 ,转到登录界面
Response.Write("<script>parent.document.location.href='Login.aspx';</script>"); ////有框架时所用
//Response.Redirect("login.aspx"); ////无框架时用
return;
}
深入思考:
由本例的解决方法可以加以延伸,比如,在存储UserID的时候,将UserID+客户端IP地址一起存进去,
则在将相应信息取出来分析的时候,可以做到:当用户在不同的计算机上先后登录的时候,则允许最近一次的登录,而将之前的登录删除!等等
ASP.net 实现禁止用户重复登录的更多相关文章
- Application作用域实现:当用户重复登录时,挤掉原来的用户
Application作用域实现:当用户重复登录时,挤掉原来的用户 一.实现思想 1.application(ServletContext)是保存在服务器端的作用域,我们在application中保存 ...
- Linux 系统强制踢掉登录用户并禁止用户再次登录系统
标注:创建一个test测试用户,test用户使用Xshel工具ssh远程登录linux操作系统. 强制踢掉登录用户方法一: [root@cloucentos6 ~]# w ...
- Linux—禁止用户SSH登录方法总结
Linux-禁止用户SSH登录方法总结 一.禁止用户登录 1.修改用户配置文件/etc/shadow 将第二栏设置为"*",如下.那么该用户就无法登录.但是使用这种方式 ...
- ASP.NET MVC 解决账号重复登录问题
解决重复登录 用到了 .net 身份票证 和Global全局处理文件 第一步 登录方法 传入用户名 private void GetOnline(string Name) { Hashtable S ...
- 使用Asp.net Identity 创建用户 、登录代码
1.Identity 1中的注册.登录.注销代码 vs 2013中自带的注册用户代码: 1.首先创建一个ApplicationUser 初始化用户名. 2.使用UserManager创建一个用户,用使 ...
- php实现单个用户禁止重复登录,防止同一用户同时登陆
<?php session_start(); //ini_set('session.auto_start', 0); //关闭session自动启动 //ini_set('session.coo ...
- ASP.NET MVC实现一个用户只能登录一次 单用户登录
现在许多网站都要求登录后才能进行进一步的操作,当不允许多用户同时登录一个帐号时,就需要一种机制,当再登录一个相同的帐号时,前面登录的人被挤下线,或者禁止后面的人登录.这里实现的是前一种功能. 网上有许 ...
- 禁止root用户远程登录
Linux修改ssh端口22 vi /etc/ssh/ssh_config vi /etc/ssh/sshd_config 然后修改为port 8888 以root身份service sshd res ...
- ASP.NET连接数据库时,提示“用户 'sa' 登录失败原因: 未与信任 SQL Server 连接相关联
用ASP.NET连接数据库时,提示"用户 'sa' 登录失败.原因: 未与信任 SQL Server 连接相关联.".解决方法:首先检查是不是web.config文件内的用户名密码 ...
随机推荐
- php实现设计模式之 命令模式
<?php /* * 命令模式:(行为模式)将一个请求封装成一个对象(命令封装成对象),从而可以使用不同的请求对客户参数化(客户的不同请求,调不同的封装对象), * 对请求排序,或者记录请求日志 ...
- Struts2入门(一)——环境搭建和简单例子(Struts2 2.5.2版本)
一.前言 1.了解三大框架 什么是框架? 框架是一种规范,一种规则,一种把技术组织起来的规则,这就是框架. 什么是三大框架(SSH),Struts.hibernate和spring的作用是什么? St ...
- #9.6课堂JS总结#变量作用域 date()对象 math()对象
一.变量的作用域 1.JavaScript的作用域链 首先看下下面这段代码: <script type="text/javascript"> var rain = 1; ...
- HTML标签界里不会再用到的标签属性(一)
为了成为一名初级前端开发工程师,最近正在探寻HTML标签的众多奥秘,果不其然,让我发现了许多被“冷落”了的标签属性. 一.<!DOCTYPE> 自从HTML5流行之后,<!DOCTY ...
- GPS数据读取与处理
GPS数据读取与处理 GPS模块简介 SiRF芯片在2004年发布的最新的第三代芯片SiRFstar III(GSW 3.0/3.1),使得民用GPS芯片在性能方面登上了一个顶峰,灵敏度比以前的产品大 ...
- iOS多线程之4.GCD简介
GCD(Grand Central Dispatch)应该是我们开发中最常用到的多线程解决方案,是苹果公司专门为多核的并行运算提出的解决方案,是基于C语言的,提供了很多非常强大的函数. GCD的优势 ...
- IOS开发基础知识--碎片44
1:App跳转至系统Settings 跳转在IOS8以上跟以下是有区别的,如果是IOS8以上可以如下设置: NSURL *url = [NSURL URLWithString:UIApplicatio ...
- parawork功能使用说明
项目整体估算 1.项目估算:依据项目属性,开发规模,参考行业平均生存率自动估算软件工作量.成本.工期 : 2.项目生产率分析:掌握研发生产率行业水平,方便项目管理 : 3.工期占比分析:了解项目关键节 ...
- ORACLE字符集基础知识
概念描叙 ORACLE数据库有国家字符集(national character set)与数据库字符集(database character set)之分.两者都是在创建数据库时需要设置的.国家 ...
- C#:枚举
1. 枚举的综合运用 public enum Color { yellow, blue, green } class Program { static void Main(string[] args) ...