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安全框架,可以帮助我们完成认证.授权.会话管 ...
随机推荐
- qt 中文乱码
首先呢,声明一下,QString 是不存在中文支持问题的,很多人遇到问题,并不是本身 QString 的问题,而是没有将自己希望的字符串正确赋给QString. 很简单的问题,"我是中文&q ...
- jq 获取name值一样的数组
<input type="text" value="" name="wid"/><input type="tex ...
- JAVA课程设计——多源教学数据管理系统
团队简介 团队名称: 419圣斗士 团队成员 姓名 成员介绍 任务分配 周炳辉(组长) 来自网络的一个大佬,穿女装很合适 poi与servlet 徐宏伟 网络中一个具有强大隐藏实力的大哥 css,部分 ...
- BEGIN-2_蓝桥杯_序列求和
问题描述 求1+++...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+++...+n的值. 样例输入 样例输出 样例输入 说明:有一些试题会给出多组样例输入输 ...
- Date类为什么设计为可变的,而不是像String一样?
首先,不得不承认,这确实是类库设计的一个错误,所以"为什么"进行了这个错误设计并没有意义.但没有事物一诞生就是完美的,我们的Java只是反应的慢了一点,再慢了一点. 更何况,Dat ...
- 接口测试3-3Excel格式
java操作Excel,需要第三方库poi #xml <dependency> <groupId>org.apache.poi</groupId> <arti ...
- 1084 Broken Keyboard (20 分)
1084 Broken Keyboard (20 分) On a broken keyboard, some of the keys are worn out. So when you type so ...
- JedisCluster模式尝试进行批量操作
搭建完redis集群后,可以通过jedis的JedisCluster来访问Redis集群,这里列出使用jedisCluster的spring bean配置方式: <bean id=" ...
- Delphi Webbrowser使用方法详解(二)
delphi如何用webbrowser模拟登录网站? 我们就以如何登录博客园来做示例: 1.要登入一个网站,首先要获取网页的源代码,我们可以通过网页菜单--查看--查看源代码来获取. 2.我们找到登录 ...
- concurrent.futures模块
1.concurrent.futures模块介绍 2.ThreadPoolExecutor线程池使用 3.ProcessPoolExecutor进程池使用 4.其他方法使用 1.concurrent. ...