因为项目需要,这两天一直在尝试和思考 重复登录的问题,
想到一些可以思考或者是运用的东西:
Session Application Dictionary MacAddress Cookie 下面将为什么考虑要使用这个而做一个分析
Session对象:保存用户信息如:UserName之类的 这样方便不同的页面访问UserName这样的对象 而且Session.SessionID 也是一个唯一的 在session过期移除对象的时候作用明显
AppLication 对象 一个不可少的对象,保存一个在线用户的一个列表,方便查看该用户是否已经登录,现在的状态是什么
Dictionary 可以在application中放入dic,方便查询和存放对象
MacAddress 对象和 Cookie 对象, 这两个对象我是想的比较深入:假如我们要在不同的浏览器中实现一个浏览器中登录了在另外的浏览器上还是登录状态这样的想法 我想 MacAddress 和Cookie对象就很有用处了. MacAddress 可以判断该对象是不是同一台计算机,而Cookie 可以代替Session存放用户信息(因为session跨浏览器是得不到值的
)
以上是我思考到的一些碎片 于是开始了整理逻辑和写代码
流程上应该是这样的:
一个用户[A]到了一个登录的页面上,输入了用户名和密码 登录了,到了一个主页面. 而有同样帐号和密码的另一个用户[B]在别的计算机也登录了,到了主页面,当A刷新的时候出现:您的帐号在别的地方已经登录了怀疑您的帐号是否被盗用,您将失去访问权限,请重新登录并且修改登录密码. 这里需求上说采用踢人的方式进行防止重复登录
流程清楚了 逻辑也就很明白了;
首先是要申请一个Application 用户登录,我们得把这用户的相关信息放置到session中,方便在主页面中使用,将 用户信息和Session.SessionID做一个键值对的关系并且放到Dictionary中 判断Application中是否有该对象[如果有该对象说明这个用户在别的地方是登录状态或者说上一次登录的状态还没有消失(session 还没有过期程序还没有移除该对象)]有该用户 将该用户从dic中移除,从application中移除此用户信息. 在重新添加该用户信息,但现在的信息和以往不同的是:key值不同sessionID 不同
Code:
string userName="";
string userPassword="";
Dictionary<string,string> dic=new Dictionary<string,string>();
//判断登录对象是否正确
if (this.TxtUserName.Text!="admin")
{
return;
}
if (this.TxtUserPassword.Text != "admin")
{
return;
}
userName = this.TxtUserName.Text.Trim();
Session["userinfo"] = userName;
//如果登录成功了
dic.Add(Session.SessionID, userName);
//将对象的信息做一个记录
if (Application["userinfo"] == null)//如果对象是空对象的话将现有的对象放到app中
{
Application["userinfo"] = dic;
}
else
{
Dictionary<string, string> appdic = new Dictionary<string, string>();
appdic = (Dictionary<string, string>)Application["userinfo"];
//先判断对象 是否是存在原来的地方
if (appdic.ContainsValue(userName))//如果它有相同的value值说明这个对象原来是有登录的
{
foreach (string var in appdic.Keys)
{
if (appdic[var]==userName)
{
appdic.Remove(var);//将对象移除,并且break 注:如果不break 程序也许会报一个错误:"集合已经修改,可能无法执行枚举操作"
break;
}
}
//将这个对象代替
}
appdic.Add(Session.SessionID,userName);
Application["userinfo"] = appdic;//将现在的对象放到application中
}
//跳转到登录以后的页面上
Response.Write("<script>location.href='default2.aspx'</script>");
}
以上的代码是登录页面的核心代码.
在主页面将要[判断的是进入主页面的用户有没有登录,有没有被踢出.
怎么判断呢? 当前登录的用户key值和value值能对应就算是
Code:
//先是判断对象是不是已经登录状态了
if (Application["userinfo"] == null || Session["userinfo"] == null)
{
Response.Write("<script>alert('您还没有登录,请先登录')</script>");
return;
}
else//判断对象中是否已经有这个对象了
{
//判断对象是否是存在的
Dictionary<string, string> appdic = new Dictionary<string, string>();
appdic = (Dictionary<string, string>)Application["userinfo"];
if (appdic.ContainsKey(Session.SessionID))//如果这个对象是存在的 说明这个对象是登录过的.
{
//没问题
LitUserName.Text = Convert.ToString(appdic[Session.SessionID]);
}
else//如果没找到,说明什么? 说明
{
//一:这个用户没用登录或者是说这用户已经过期
Response.Write("<script>alert('您当前登录已经过期或者在别的地方已经登录了,请您重新登录');location.href='default.aspx'</script>");
}
}
在Global文件中唯一要做的就是将过期的session做一个移除
因为考虑到移除session的不方便处所以就将session.sessionid做为dic的key,这样就可以很方便的将该对象做一个移除
Code:
/// <summary>
/// 当session 移除的时候发生
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Session_End(object sender, EventArgs e)
{
// 在会话结束时运行的代码。
// 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
// InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
// 或 SQLServer,则不会引发该事件。
if (Application["userinfo"] != null)
{
System.Collections.Generic.Dictionary<string, string> dic = (System.Collections.Generic.Dictionary<string, string>)Application["userinfo"];
if (dic.ContainsKey(Session.SessionID))//如果包含这个对象 移除这个对象
{
dic.Remove(Session.SessionID);
}
Application["userinfo"] = dic;
}
暂时没有考虑到相同的计算机上不同的浏览器使用问题 先将得到MacAddress的方法贴下以免以后难找:
/// <summary>
/// 这是得到本机编号
/// </summary>
/// <returns></returns>
public string GetNetCardMacAddress()
{
ManagementClass mc;
ManagementObjectCollection moc;
mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
moc = mc.GetInstances();
string str = "";
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
str = mo["MacAddress"].ToString();
}
return str;
}