网上有很多介绍单点登录的文章,但多为架构设计以及概念性文章,而本文将介绍单点登录的具体具体实现

利用哈希表,作为保存登录用户的队列
        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#实现支持单点登录的一个存储用户信息的类的更多相关文章

  1. python实现用户登陆(sqlite数据库存储用户信息)

    python实现用户登陆(sqlite数据库存储用户信息) 目录 创建数据库 数据库管理 简单登陆 有些地方还未完善. 创建数据库 import sqlite3 #建一个数据库 def create_ ...

  2. C# 脚本代码自动登录淘宝获取用户信息

    C# 脚本代码自动登录淘宝获取用户信息   最近遇到的一个需求是如何让程序自动登录淘宝, 获取用户名称等信息. 其实这个利用SS (SpiderStudio的简称) 实现起来非常简单. 十数行代码就可 ...

  3. php 微信登录 公众号 获取用户信息 微信网页授权

    php 微信登录 公众号 获取用户信息 微信网页授权 先自己建立两个文件: index.php  和  getUserInfo.php index.php <?php //scope=snsap ...

  4. CAS单点登录之mysql数据库用户验证及常见问题

    前面已经介绍了CAS服务器的搭建,详情见:搭建CAS单点登录服务器.然而前面只是简单地介绍了服务器的搭建,其验证方式是原始的配置文件的方式,这显然不能满足日常的需求.下面介绍下通过mysql数据库认证 ...

  5. 微信小程序维护登录态与获取用户信息

    前言. 微信小程序的运行环境不是在浏览器下运行的.所以不能以cookie来维护登录态.下面我就来说说我根据官方给出的方法来写出的维护登录态的方法吧. 一.登录态维护 官方的文档地址:https://m ...

  6. Cas单点登录配置数据查询用户

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  7. 【转】如何打开注册表编辑器中存储用户信息的SAM文件?

    sam文件怎么打开 (Security Accounts Manager安全帐户管理器)负责SAM数据库的控制和维护.SAM数据库位于注册表HKLM\SAM\SAM下,受到ACL保护,可以使用rege ...

  8. 微信订阅号里实现oauth授权登录,并获取用户信息 (完整篇)

    摘要 这段时间一直有人问我,订阅号实现的oauth授权登录的问题,之前写的比较简单,很多人不明白.众所周知,微信公众号分订阅号.服务号.企业号:每个号的用途不一样,接口开放程度也不一样.微信还有个扯淡 ...

  9. Shiro与CAS整合实现单点登录

    1.简介 CAS:Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法. Shiro:Apache Shiro是一个Java安全框架,可以帮助我们完成认证.授权.会话管 ...

随机推荐

  1. hadoop入门学习教程--DKHadoop完整安装步骤

    使用hadoop版本是DKH标准三节点发行版,DKHadoop版本的易用性比较好,环境部署要简单的多,参考此篇安装前请先下载DKHadoop版本,网盘链接:https://pan.baidu.com/ ...

  2. 静态编译opencv3.4.0

    问题: 编译了静态库之后可以不要那么多dll 解决办法: 其实和编译动态库的区别就在于: Cmake里面操作的时候,去掉下面这个选项的勾勾 BUILD_SHARED_LIBS

  3. Django url反向解析与路由分发名称空间

    url反向解析 url.py from django.conf.urls import url from django.contrib import admin from app01 import v ...

  4. Yii 用户登录验证

    http://blog.sina.com.cn/s/blog_685213e70101mo4i.html 1)首先在model文件夹中新建文件 LoginForm.php 代码如下 <?php ...

  5. Hadoop文件系统支持释疑之S3

    一.引言 Hadoop版本提供了对多种文件系统的支持,但是这些文件系统是以何种方式实现的,其实现原理是什么以前并没有深究过.今天正好有人咨询我这个问题:Hadoop对S3的支持原理是什么?特此总结一下 ...

  6. 实验八 c排序算法

    8.1 #include<stdio.h> int main(){ int a[5],i,j,k,t,z; //输入5个元素进入数组 for(i=0;i<5;i++) scanf(& ...

  7. Makefile | Linux嵌入式编程 使用详细图解

    针对的是对Makefile一点都不会的小白哦! 练习之前我们要做好准备: (1):第一步创建一个目录,因为实验过程中生成的文件会很多,不要把你系统里的文件搞得乱七八糟. [cjj@bogon ~]$ ...

  8. Logstash之四:logstash接收kafka数据

    3.kafka+logstash整合logstash1.5以后已经集成了对kafka的支持扩展,可以在conf配置中直接使用 vim /etc/logstash/conf.d/pay.conf inp ...

  9. 正则的使用及replace细讲

    1.var reg=/./ 与 var reg=/\./的区别? .代表任意一个字符 \.而后者代表这个字符串中得有一个. 2.?的使用 如果单独的一个字符后面带? /\d?/ 代表1个或0个这个字符 ...

  10. 1067 Sort with Swap(0, i) (25 分)

    1067 Sort with Swap(0, i) (25 分) Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy ...