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

利用哈希表,作为保存登录用户的队列
        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. JS 检测浏览器中是否安装了特定的插件

    1.检测非IE浏览器 可以使用plugins数组来达到这个目的,例: //检测插件(在IE中无效) function hasPlugin(name){ name = name.toLowerCase( ...

  2. gitlab配合walle搭建发布系统

    理解walle实现发布代码的原理: ​ 宿主机:walle系统搭建的服务器以及拉取gitlab代码的服务器,这个时候gitlab一般都是另外一台服务器. 目标机器:版本最终发布的目的机器,或者目的机群 ...

  3. Elasticsearch 基础入门

    原文地址:Elasticsearch 基础入门 博客地址:http://www.extlight.com 一.什么是 ElasticSearch ElasticSearch是一个基于 Lucene 的 ...

  4. 关于有时候导入maven项目时候报错(有红色叹号,类中导入的包提示"the import java.util cannot be resolve,")

    ------解决方案--------------------解决方案:右键项目-------buildpath--------最下面那个configura...的选择libraries找到JRE(这个 ...

  5. tomcat和servlet的关系

    一.什么是servlet? 处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西.理解这个的前提是了解一些http协议的东西,并且知道 ...

  6. git Push failed: Could not read from remote repository 解决方案

    解决的办法很简单,进入Android Studio配置界面,选择Version Control——>Git,在右边界面切换SSH下拉选项为Native,最后重新提交.如果解决你的问题,记得分享哦 ...

  7. wxWidgets:动态EVENT绑定

    我们已经看到如何使用静态EVENT TABLE来处理EVENT:但这种方式不够灵活.下面我们来看看如何在Event和处理函数间实现动态Bind. 仍然以那个简陋的Frame作为例子. 首先删除所有的静 ...

  8. bzoj3631 松鼠的新家

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  9. Oracle学习操作(5)触发器

    Oracle触发器 一.触发器简介 具备某些条件,由数据库自动执行的一些DML操作行为: 二.语句触发器 现在数据库创建t_book表:t_booktype表:t_book表的typeid存在外键参考 ...

  10. onload属性使用方法

    onload事件属性是页面的图片文字等全部加载完毕后执行的事件 window.onload=fun1;function fun1(){    document.getElementsByTagName ...