用户登录:顾名思义。大家的肯定会理解其中的意思,我也懒得废话。
但是作为一个网站后台的管理用户,不管是什么样的权限,什么样的级别(又是废话)要登录后台,那么,这个用户在这一时间段内,只能登录一次。而不能反复,或者在异地登录。
当然:这样的做法就是为了。保证后台用户登录的唯一性。不然的话,同时登陆的害处,也会让大家烦不胜烦,更重要的是,对数据的更新问题了。具体的就不说了。
废话少说:直接进入正题,来看看我是如何实现,单一用户登录的。
网上也找过很多的资料,居然都是单点登录,fuck。
进入正题了:
保证用户的唯一登陆:那么就需要将已登录的用户信息保存起来,在有用户登录的情况下,来对比这个已登录用户的队列,判断这个用户是否存在?如果存在,不好意思,你不能登录。若是不存在,则存储,直到释放。
登录的模块就不写了。直接进入用户信息存储的模块
if(user){//如果用户信息在数据库中存在且用户信息正确。
string strUserId = UserName.Text.Trim();//用户输入
//以字典为存储对象:存储用户名,和用户登录的时间。存入全局变量中。
Dictionary<string, DateTime> dis = Application.Get("GLOBAL_USER_LIST") as Dictionary<string, DateTime>;
if (dis == null)
{
dis = new Dictionary<string, DateTime>();
}
else
{
//判断字典中是否有数据?为什么呢?如果没有数据的话,那就说明你是个新用户,直接存储,如果有的话,那么记性对比。
//当然,这个字典中的key是你当前输入的用户名。为的就是来判断,当前的这个key是否存在。如果存在的话,就说明已经登陆过了。
//上边的说法并不确切,请继续向下看。
//session 没有失效啊。所以key依然存在。但是已经关闭浏览器了。会话已经结束了。
//下面的代码就是解决上面问题的。key存在,给其value加上30s来和当前登录的时间进行比较。
//如果当前时间小于加上30s的value的话。说明session还未释放。那么是无法登录的。
//反之:则可以登录,因为如果大于的话,就会移除这个key,那么在字典中就没有了当前登录用户的信息了。既然没有,就更谈不上重复登录了。
if (dis.Count != 0)
{
DateTime dt = dis[strUserId].AddSeconds(30);
if (System.DateTime.Now.CompareTo(dt) > 0)
{
dis.Remove(strUserId);
Application.Add("GLOBAL_USER_LIST", dis);
}
}
}
int x = 0;
//这里的foreach的作用是什么呢?就是判断当前登录用户是否在字典中。如果在,就是重复登录。如果不在,那就登录把
foreach (string userName in dis.Keys)
{
if (strUserId == userName)
{
x = 1;
break;
}
}
if (x == 1)
{
Response.Write("<Script>alert('该用户已经登录');location.href='SignIn.aspx';</Script>");
}
else
{
//可以登录。当然就要把登陆的信息记录到字典中,保持登录状态的
dis.Add(strUserId, System.DateTime.Now);
Application.Add("GLOBAL_USER_LIST", dis);
Respose.write('你要去的url');
}
}
上面是登录的模块,意在判断用户是否重新登录的。当然,光是有这个东西是不够的。还需要下面这个页面。
check_user_login.aspx
页面中什么html元素都不需要,只需要一个标头而已,剩下全部删除,就留下<%%>部分,
其中的具体代码也是非常简单:
//获取传递过来的参数:登录的用户名
if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["CheckName"]))
{
string username = HttpContext.Current.Request.QueryString["CheckName"].ToString();
Dictionary<string, DateTime> dis = new Dictionary<string, DateTime>();
//从Application中取出字典。
dis = (Dictionary<string, DateTime>)Application.Get("GLOBAL_USER_LIST");
if (dis[username] != null)
{
//加30s的判断。
DateTime dt = dis[username].AddSeconds(30);
if (System.DateTime.Now.CompareTo(dt) > 0)
{
//当前时间大于加上30s的时间,移除key,释放session,更新application
dis.Remove(username);
Session.Abandon();
Application.Add("GLOBAL_USER_LIST", dis);
}
else
{
//当前时间小于加上30s的时间。那么移除key,重新添加这个key,更新value,更新application
dis.Remove(username);
dis.Add(username, dt);
Session.Timeout = 1;
Application.Add("GLOBAL_USER_LIST", dis);
}
//为了在firebug中查看,可以不要
Response.Write(dis[username].ToString());
}
}
到了这里,大家一定非常想知道,上面这个页面的参数是哪里来的?不着急,下面就是参数来了。
var x = 0;
function myRefresh1() {
$.ajax({
type: "GET",
url: “check_user_login.aspx”,
dataType: "html",
data: "CheckName=" + $("#ctl00_User_Name").text()
//$("#ctl00_User_Name").text()这个东西就是传过去的参数:这个是从页面上得到的。当然了,你的后台肯定有个地方显示用户登录信息的把。就是抓到这个用户登录信息中的用户名传过去
});
x++;
if (x < 60) //这个方法执行60次,也就是Session真正的过期时间是30分钟
{
setTimeout("myRefresh1()", 30 * 1000); //30秒
}
}
myRefresh1();
现在就来解释session把。在webconfig中呢。设置session的过期时间为1分钟。但是每隔30s就会更新一次session,在check_user_login.aspx中体现出来了。这样的话,session的过期时间算下来,就是30分钟30秒。足够了把。很多东西都是可以自己改的,大家可以根据自己的实际情况进行修改。你可以用ajax 10分钟更新一次session的过期时间。当然session的过期时间一定要大于10分钟才行。也可以循环跟新一亿次........
Global.asax是不可缺少的部分,主要是想要其中的Session_end事件
BasePage bp = new BasePage();
string strUserId = bp.Get_Login_User_Info;//获取当前登录用户的用户名,也就是字典中的key。移除它,更新application。完美退出
System.Collections.Generic.Dictionary<string, DateTime> dis = Application.Get("GLOBAL_USER_LIST") as System.Collections.Generic.Dictionary<string, DateTime>;
if (strUserId != null && dis != null)
{
dis.Remove(strUserId);
Application.Add("GLOBAL_USER_LIST", dis);
}
当然,上面这几行代码,也是写在你的登出按钮事件中的。
好了,单一登录,就此结束,绝对是可以的。因为我现在的网站就是这样整的。
这同样是第一中解决方案了。
同样的,页面刷新后,js的循环更新字典,在每次刷新页面后,也是从0开始,循环60此结束,如果你频繁的跳转,永不退出。本来想着就是30分钟,可是觉得永不退出也蛮好的。
不刷新页面的话,30分钟就需要重新登录了。
如果关闭浏览器,session也就是1分钟过期,同样的, 进入登录页面还有个字典的value 的判断。保证了万无一失。
ok。打完收工