C#实现支持单点登录的一个存储用户信息的类
网上有很多介绍单点登录的文章,但多为架构设计以及概念性文章,而本文将介绍单点登录的具体具体实现
利用哈希表,作为保存登录用户的队列
private static Hashtable m_userList;
设置用户在线超时的时限(我设置的是30分钟,可以根据自己的需求自行修改)
private static TimeSpan m_tsSub = new TimeSpan(0, 30, 0);
设置哈希表初始化为同步封装(为了线程安全)
m_userList = Hashtable.Synchronized(new Hashtable());
设置了几种方式
1、登录信息在数据库中验证成功后调用AddUserToList(string userName, long sessionID)
2、除登录外其他所有功能调用之前首先调用该方法 CheckUserLogin(string userName, long sessionID)
在第一种方式中,需要处理“如果用户已经登录过,则只更新登录流水号及操作时间,否则新加入队列"
该类还有个最重要的步骤就是检查保存在队列中的用户在线是否超过时限,该方法供线程调用,以便检查用户是否在线,需要保存待清理的超时在线用户的临时队列,线程每隔1分钟执行检查清理操作,遍历保存在线用户的哈希表,如果有超时的在线用户,将超时用户时放入临时的队列中,
检查完哈希表之后再进行清理操作,
不能在检查过程中执行哈希表的删除键值操作,否则会出现异常。
特别注意的是如果有超时的在线用户则进行清理操作
具体代码如下
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading; namespace DllServiceLibrary
{
class HashElement
{
long m_SessionID;
DateTime m_Time; public long SessionID
{
get { return m_SessionID; }
set { m_SessionID = value; }
} public DateTime Time
{
get { return m_Time; }
set { m_Time = value; }
} public HashElement()
{
m_SessionID = -1;
m_Time = DateTime.Now;
}
} public static class UserLogin
{
//哈希表,作为保存登录用户的队列
private static Hashtable m_userList;
//检查用户在线是否超时的线程
//private static Thread m_threadQueue;
//用户在线超时的时限(30分钟)
private static TimeSpan m_tsSub = new TimeSpan(0, 30, 0); //public static UserLogin()
public static void Init()
{
//哈希表初始化为同步封装(线程安全)
m_userList = Hashtable.Synchronized(new Hashtable());
//初始化线程
//m_threadQueue = new Thread(CheckListTO);
//m_threadQueue.IsBackground = true; //设置为后台线程
//m_threadQueue.Start();
} public static void Empty()
{
//if (m_threadQueue.IsAlive)
//{
// m_threadQueue.Abort();
//}
m_userList.Clear();
} /// <summary>
/// 登录信息在数据库中验证成功后调用
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="sessionID">登录流水号</param>
/// <returns>
/// 0:用户及登录流水号成功保存于队列
/// -1:保存失败
/// </returns>
public static int AddUserToList(string userName, long sessionID)
{
WriteLog.WriteData w = new WriteLog.WriteData();
int ret = 0;
try
{
HashElement hashElt = new HashElement();
hashElt.SessionID = sessionID;
//如果用户已经登录过,则只更新登录流水号及操作时间,否则新加入队列
lock (m_userList.SyncRoot)
{
if (m_userList.ContainsKey(userName))
{
m_userList[userName] = hashElt;
}
else
{
m_userList.Add(userName, hashElt);
}
}
}
catch (Exception exp)
{
//System.Console.Out.WriteLine(exp.StackTrace);
//System.Console.Out.WriteLine(exp.Message);
w.WriteLine(exp.Message + exp.StackTrace, 01);
ret = -1;
}
return ret;
} /// <summary>
/// 除登录外其他所有功能调用之前首先调用该方法
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="sessionID">登录流水号</param>
/// <returns>
/// 0:验证用户登录成功
/// -1:验证用户登录失败
/// -2:用户未登录
/// -3:用户已重新登录或在别处登录
/// </returns>
public static int CheckUserLogin(string userName, long sessionID)
{
//WriteLog.WriteData w = new WriteLog.WriteData();
int ret = 0;
try
{
lock (m_userList.SyncRoot)
{
if (m_userList.ContainsKey(userName))
{
HashElement hashElt = m_userList[userName] as HashElement;
if (hashElt.SessionID.Equals(sessionID))
{
hashElt.Time = DateTime.Now;
m_userList[userName] = hashElt;
ret = 0;
}
else
{
ret = -3;
}
}
else
{
ret = -2;
}
}
}
catch
{
//w.WriteLine(exp.Message + exp.StackTrace, 02);
//System.Console.Out.WriteLine(exp.StackTrace);
//System.Console.Out.WriteLine(exp.Message);
ret = -1;
}
return ret;
} /// <summary>
/// 检查保存在队列中的用户在线是否超过时限,该方法供线程调用
/// </summary>
private static void CheckListTO()
{
//WriteLog.WriteData w = new WriteLog.WriteData();
try
{
//保存待清理的超时在线用户的临时队列
List<string> toKeys = new List<string>();
while (true)
{
//线程每隔1分钟执行检查清理操作
Thread.Sleep(1000 * 60);
//遍历保存在线用户的哈希表
lock (m_userList.SyncRoot)
{
foreach (DictionaryEntry deElt in m_userList)
{
//如果有超时的在线用户,将超时用户时放入临时的队列中,
//检查完哈希表之后再进行清理操作
//不能在检查过程中执行哈希表的删除键值操作,否则会出现异常。
HashElement htElt = deElt.Value as HashElement;
if (DateTime.Now - htElt.Time > m_tsSub)
{
toKeys.Add((string)deElt.Key);
}
}
//如果有超时的在线用户则进行清理操作
if (0 < toKeys.Count)
{
foreach (string key in toKeys)
{
m_userList.Remove(key);
}
toKeys.Clear();
}
}
}
}
catch
{
//System.Console.Out.WriteLine(exp.StackTrace);
//System.Console.Out.WriteLine(exp.Message);
//w.WriteLine(exp.Message + exp.StackTrace, 03);
}
} /// <summary>
/// 获取当前在线用户统计数
/// </summary>
/// <returns>统计数</returns>
public static int GetUserCount()
{
//WriteLog.WriteData w = new WriteLog.WriteData();
int count = 0;
try
{
lock (m_userList.SyncRoot)
{
count = m_userList.Count;
}
}
catch
{
//System.Console.Out.WriteLine(exp.StackTrace);
//System.Console.Out.WriteLine(exp.Message);
//w.WriteLine(exp.Message + exp.StackTrace, 04);
}
return count;
}
}
}
C#实现支持单点登录的一个存储用户信息的类的更多相关文章
- python实现用户登陆(sqlite数据库存储用户信息)
python实现用户登陆(sqlite数据库存储用户信息) 目录 创建数据库 数据库管理 简单登陆 有些地方还未完善. 创建数据库 import sqlite3 #建一个数据库 def create_ ...
- C# 脚本代码自动登录淘宝获取用户信息
C# 脚本代码自动登录淘宝获取用户信息 最近遇到的一个需求是如何让程序自动登录淘宝, 获取用户名称等信息. 其实这个利用SS (SpiderStudio的简称) 实现起来非常简单. 十数行代码就可 ...
- php 微信登录 公众号 获取用户信息 微信网页授权
php 微信登录 公众号 获取用户信息 微信网页授权 先自己建立两个文件: index.php 和 getUserInfo.php index.php <?php //scope=snsap ...
- CAS单点登录之mysql数据库用户验证及常见问题
前面已经介绍了CAS服务器的搭建,详情见:搭建CAS单点登录服务器.然而前面只是简单地介绍了服务器的搭建,其验证方式是原始的配置文件的方式,这显然不能满足日常的需求.下面介绍下通过mysql数据库认证 ...
- 微信小程序维护登录态与获取用户信息
前言. 微信小程序的运行环境不是在浏览器下运行的.所以不能以cookie来维护登录态.下面我就来说说我根据官方给出的方法来写出的维护登录态的方法吧. 一.登录态维护 官方的文档地址:https://m ...
- Cas单点登录配置数据查询用户
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 【转】如何打开注册表编辑器中存储用户信息的SAM文件?
sam文件怎么打开 (Security Accounts Manager安全帐户管理器)负责SAM数据库的控制和维护.SAM数据库位于注册表HKLM\SAM\SAM下,受到ACL保护,可以使用rege ...
- 微信订阅号里实现oauth授权登录,并获取用户信息 (完整篇)
摘要 这段时间一直有人问我,订阅号实现的oauth授权登录的问题,之前写的比较简单,很多人不明白.众所周知,微信公众号分订阅号.服务号.企业号:每个号的用途不一样,接口开放程度也不一样.微信还有个扯淡 ...
- Shiro与CAS整合实现单点登录
1.简介 CAS:Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法. Shiro:Apache Shiro是一个Java安全框架,可以帮助我们完成认证.授权.会话管 ...
随机推荐
- python列表中的pop
pop()将列表指定位置的元素移除,同时可以将移除的元素赋值给某个变量,不填写位置参数则默认删除最后一位. pop()根据键将字典中指定的键值对删除,同时可以将删除的值赋值给变量. a = [1, 2 ...
- JAVA课程设计——多源教学数据管理系统
团队简介 团队名称: 419圣斗士 团队成员 姓名 成员介绍 任务分配 周炳辉(组长) 来自网络的一个大佬,穿女装很合适 poi与servlet 徐宏伟 网络中一个具有强大隐藏实力的大哥 css,部分 ...
- Java技术专题之JVM你的内存泄露了吗?
一.从一个例子开始 关于JVM的内存泄露,让我们从下面一个例子开始吧,大家来判断一下如果按照下面这种分配方式,会不会出现内存泄露呢? import java.util.List; import jav ...
- bzoj1050 旅行
Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大 ...
- [转]C# 系统应用之鼠标模拟技术及自动操作鼠标
原文网址: C# 系统应用之鼠标模拟技术及自动操作鼠标 游戏程序的操作不外乎两种——键盘输入控制和鼠标输入控制,几乎所有游戏中都使用鼠标来改变角色的位置和方向,本文主要是讲述如何使用C# ...
- python selenium-9 grid模式
grid是进行分布式测试的工具,由一个hub主节点和若干个node代理节点组成 1.下载Selenium Standalone Server 下载地址:https://www.seleniumhq.o ...
- grep正则表达的零宽断言
先看一组神奇的命令 [root@elastix82 tmp]# echo $html111<td>aaa</td>222[root@elastix82 tmp]# [root@ ...
- 关于单独使用ckfinder时去除版本号和提示信息的破解
前端时间用ckfinder2.3时 吧他破解了 发现在火狐下报了一个这个错.....getItem() is undefinder 一气之下就把报错的那句话if()语句给删了 没想到歪打正着 ...
- 并发工具类(五) Phaser类
前言 JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...
- uva-10160-枚举
若当前搜索到的城市n前面1-n-1编号的城市中有没有通电的,则永远也无法输送电力给那个城市,因为在剪枝时附加了和此结点连接的最大结点小于当前的结点 这段 for(int i = 1; i < c ...