利用HttpModuler实现WEB程序同一时间只让一个用户实例登陆
*/
我在们使用ASP.Net开发WEB网站时,有的时候是不让同一个用户名在同一时间进行多次登陆的。
为了不影响原来的整个网站,我选择使用了HttpModuler来实现。
先让所有的Page从自己的Page类:BasePage类继承,并实现 ISigleLogin接口。相关代码如下:
{
string SigleUserLoginId { get; }
void SigleUserLogout();
}
{
public BasePage()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (Session["UserId"] == null)
{
Response.Write("你还没有登陆");
Response.Redirect("login.aspx");
}
}
ISingleLogin 成员#region ISingleLogin 成员
public string SigleUserLoginId
{
get
{
if (Session["UserId"] != null)
{
return Session["UserId"].ToString();
}
else
return "";
}
}
public void SigleUserLogout()
{
Session.Abandon();
Response.Write("你在别处已经登陆,强制退出本次登陆!");
}
#endregion
}
然后在Web.config中加入HttpModuler:
<httpModules>
<add name="SingleLogin" type="BNet.Web.Modulers.SingleLoginModuler"/>
</httpModules>
</system.web>
相关的SigleLoginModuler代码如下:
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.UI;
namespace BNet.Web.Modulers
{
/**//// <summary>
/// SingleLoginModuler 的摘要说明
/// </summary>
public class SingleLoginModuler : System.Web.IHttpModule
{
const string sigle_login_userid = "evlon_siglelogin_userid";
const string sigle_pre_logout_sessionid = "evlon_sigle_pre_logout_sessionid";
static StringLifeValueDictionary loginedUserIdDictionary = null;
static StringLifeValueDictionary LoginedUserIdDictionary
{
get
{
if (loginedUserIdDictionary == null)
{
loginedUserIdDictionary = new StringLifeValueDictionary();
}
else
{
List<string> listRemove = new List<string>();
StringLifeValueDictionary.Enumerator iter = loginedUserIdDictionary.GetEnumerator();
while (iter.MoveNext())
{
if (iter.Current.Value.life < DateTime.Now)
{
listRemove.Add(iter.Current.Key);
}
}
foreach (string key in listRemove)
{
loginedUserIdDictionary.Remove(key);
}
}
return loginedUserIdDictionary;
}
}
static StringLifeValueDictionary preLogoutSessionIdDictionary = null;
static StringLifeValueDictionary PreLogoutSessionIdDictionary
{
get
{
if (preLogoutSessionIdDictionary == null)
{
preLogoutSessionIdDictionary = new StringLifeValueDictionary();
}
else
{
List<string> listRemove = new List<string>();
StringLifeValueDictionary.Enumerator iter = preLogoutSessionIdDictionary.GetEnumerator();
while (iter.MoveNext())
{
if (iter.Current.Value.life < DateTime.Now)
{
listRemove.Add(iter.Current.Key);
}
}
foreach (string key in listRemove)
{
preLogoutSessionIdDictionary.Remove(key);
}
}
return preLogoutSessionIdDictionary;
}
}
public SingleLoginModuler()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
IHttpModule 成员#region IHttpModule 成员
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication context = sender as HttpApplication;
IHttpHandler httpHandler = context.Context.CurrentHandler;
if (httpHandler is ISingleLogin)
{
ISingleLogin sl = httpHandler as ISingleLogin;
string suid = sl.SigleUserLoginId;
if (suid != string.Empty)
{
if (PreLogoutSessionIdDictionary.ContainsKey(context.Session.SessionID))
{
//这个用户应该强制登出
PreLogoutSessionIdDictionary.Remove(context.Session.SessionID);
Page page = (Page)httpHandler;
page.PreInit += new EventHandler(page_PreInit);
}
else if (!LoginedUserIdDictionary.ContainsKey(suid))
{
LoginedUserIdDictionary.Add(suid, new LifeValue(context.Session.SessionID));
}
}
}
}
void page_PreInit(object sender, EventArgs e)
{
Page page = sender as Page;
ISingleLogin sl = page as ISingleLogin;
if (sl != null)
{
sl.SigleUserLogout();
page.Response.End();
}
}
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
//从LogineduserId 里找到和当前用户一样的用户ID的SessionId
HttpApplication context = sender as HttpApplication;
IHttpHandler httpHandler = context.Context.CurrentHandler;
if (httpHandler is ISingleLogin)
{
ISingleLogin sl = httpHandler as ISingleLogin;
string suid = sl.SigleUserLoginId;
if (suid != string.Empty)
{
if (LoginedUserIdDictionary.ContainsKey(suid))
{
string sessionId = LoginedUserIdDictionary[suid].value;
if (sessionId != context.Session.SessionID)
{
if (!PreLogoutSessionIdDictionary.ContainsKey(sessionId))
{
PreLogoutSessionIdDictionary.Add(sessionId,new LifeValue(suid));
}
LoginedUserIdDictionary.Remove(suid);
}
}
else
{
LoginedUserIdDictionary.Add(sl.SigleUserLoginId, new LifeValue( context.Session.SessionID));
}
}
}
}
#endregion
}
public class LifeValue
{
public string value;
public DateTime life;
public LifeValue(string value)
{
this.value = value;
this.life = DateTime.Now.AddMinutes(HttpContext.Current.Session.Timeout + 5);
}
}
public class StringLifeValueDictionary : Dictionary<string, LifeValue>
{
}
public interface ISingleLogin
{
string SigleUserLoginId { get; }
void SigleUserLogout();
}
}
转载于:https://www.cnblogs.com/ghd258/archive/2006/03/21/354569.html
利用HttpModuler实现WEB程序同一时间只让一个用户实例登陆相关推荐
- 【Spring Security】如何实现多设备同一时间只允许一个账号登录(即前登录用户被后登录用户挤下线)?只需简单两步!
1.需求分析 在同一个系统中,我们可能只允许一个用户在一个终端上登录,一般来说这可能是出于安全方面的考虑,但是也有一些情况是出于业务上的考虑,需求就是业务原因要求一个用户只能在一个设备上登录. 要实现 ...
- 用Redis实现频繁操作的拦截,例如一天内只允许一个用户登录5次
上次看到一个问题:如何用Redis实现只允许一个用户一天内登录五次. 想到Redis中可以给string设置过期时间,所以我们可以利用这个特性来实现. 作为一个java程序猿,我们使用Jedis,具体 ...
- python字典通讯录_Python利用字典将两个通讯录文本合并为一个文本实例
本文实例主要实现的是利用字典将两个通讯录文本合并为一个文本,具体代码如下: def main(): ftele1=open("d:\TeleAddressBook.txt",&qu ...
- 利用JCreator调试web程序
使用eclipse,idea等等工具开发java时,都比较笨重,因此,笔者想着精简的原则,尝试使用Jcreator开展调试,查阅了部分网友的材料,加上自己的琢磨,现将心得和大家分享下. 当前环境:JC ...
- 微信小程序 解决时间只显示年月日的问题(手机端显示NAN-NAN-NAN)
const iosTime=(date)=>{date = new Date(date.replace(/-/g, "/"));let year = date.getFull ...
- javaweb实现单点登录,防止重复登录,获取sessionid,对session及时销毁回收,只允许一个用户登录,结合struts2实现
首先我们目的是实现一个单点登录,即只允许单个账户单个登录. 实现异地与同地登录判断 要将先登录的用户强制下线.不免用到session. 单点登录的最大难题:已经登录且重复登录的用户的session怎么 ...
- java只允许一个用户登陆_spring boot security只允许一个用户(test1)登录
我使用spring boot security编写了登录功能 . 这是SecurityConfig类中的configureGlobal方法,扩展了WebSecurityConfigurerAdapte ...
- Win7多用户下开机只显示一个用户
1.使用快捷键 Win + R 打开运行对话框 2.在运行对话框中输入 Regedit 点击确认按钮 3.依次展开注册表路径 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsof ...
- 利用TPTP对Java程序进行性能测试
简单地说,TPTP 是一个EclipseFoundation 顶级项目,它的目标是:构建一个通用的可扩展的基于标准的工具平台,软件开发人员可以在这个平台上创建专用的可互操作的...测试和性能工具. T ...
最新文章
- Linux下使用diff和patch制作及打补丁(已经实践可行!)
- golang bytes包 []byte 字节切片 简介
- 外媒分析:iPhone销量低于预期是中国市场疲软影响的
- java nio proactor_reactor模式与java nio
- win764位和32位有什么区别_32位、64位它们是什么关系?它们又有什么区别?
- 强制将IE8设置为IE7兼容模式来解析网页
- 深入理解linux网络技术内幕读书笔记(十)--帧的接收
- Hbase面试 描述 Hbase 中 scan 和 get 的功能以及实现的异同.
- 三大器之------生成器
- 数学问题(三):最小公倍数、最大公约数
- 秋名山直播php源码,【斗鱼直播源】浏览器抓取真实直播源地址(纯前端JS PHP解析源码)...
- CMOS门基本工作原理
- Mysql如何跨库查询数据?
- 新的开始-轩宇的c++学习之路
- 供应商关系管理系统SRM
- 【产品志】显示器的选购
- 辰视智能董事长冯良炳博士接受深圳广电集团众创TV专访
- OSDI 2021 VEGITO 论文阅读
- 逻辑回归LR模型简介
- 软件设计师考试-软件工程
热门文章
- golang内存对齐
- 尊重个体多样性,科学人文终统一
- #ifdef __cplusplus extern “C” { #endif的作用!
- UART0串口编程(四):UART0串口编程之在UC/OS—II中遭遇的危机
- 贫血模型,充血模型(领域驱动设计)
- 宜信开源|详解PaaS平台LAIN的功能和架构
- vue[源码]你不知道的observe!
- Java 虚拟机经典六问
- 用js获取当前月份的天数
- Centos7安装go-1.9.2