• 单点登陆单web应用的单点登陆


    概述
    单点登陆(SSO-Single Sign On)简而言之就是能够通过认证系统能够使用户在一个系统登陆后就可以在权限允许范围内访问其他的系统而不需要重新登陆,或者保证用户登陆的单一性即用户在同一时间只能有一个登陆状态.

    单点登陆有很多种:根据系统的架构可以分为C/S系统的,B/S系统的或者两者混合系统的;根据应用的多少可以分为单应用的和多应用的;根据系统的网络环境还可以分为单域的和跨域的.

    这个文章要讨论的是.NET框架下B/S模式单个应用的单点登陆:保证用户登陆的后单一性即后一个用户登陆后前一个用户将会自动退出系统.系统的认证原理:用户信息存储在数据库中.

    原理
    用户登陆后的信息是存储在Session中(Session的值实际上是存储在server上的),每个Session的SessionID是不同的用户第二次登陆之前检测Session中是否已经有该用户登陆如果有则重写Session中的值,使第一个登陆用户的Session失效从而退出系统.否则直接登陆系统.

    实例代码

    1.用于存储用户登陆信息的类UserCollection.cs

        public class UserCollection
        
    {
            
    static UserCollection()
            
    {
                
    if (loginUser == null)
                
    {
                    loginUser 
    = new Hashtable();
                }

            }


            
    public enum UserStatus
            
    {
                Usual,
                Change,
                NoUser
            }


            
    private static Hashtable loginUser;
            
    public static Hashtable LoginUser
            
    {
                
    get return loginUser; }
                
    set { loginUser = value; }
            }


            
    public static void AddUser(string userId, string guid)
            
    {
                LoginUser.Add(userId, guid);
            }


            
    public static void Login(string userId, string guid)
            
    {
                UserStatus status 
    = GetUserStatus(userId, guid);
                
    if (status == UserStatus.NoUser)
                
    {
                    AddUser(userId, guid);
                }

                
    else if (status == UserStatus.Change)
                
    {
                    UpdateUser(userId, guid);
                }

                
    else
                
    {
                }

            }


            
    public static void LogOff(string userId)
            
    {
                DeleteUser(userId);
            }


            
    public static void LogOff(string userId, string guid)
            
    {
                
    if (guid == null)
                    DeleteUser(userId);
                
    else
                    DeleteUser(userId, guid);
            }


            
    public static void DeleteUser(string userId)
            
    {
                
    if (LoginUser.ContainsKey(userId))
                
    {
                    LoginUser.Remove(userId);
                }

            }


            
    public static void DeleteUser(string userId, string guid)
            
    {
                
    if (LoginUser.ContainsKey(userId))
                
    {
                    
    if (guid == LoginUser[userId].ToString())
                    
    {
                        LoginUser.Remove(userId);
                    }

                }

            }


            
    public static void UpdateUser(string userId, string newGuid)
            
    {
                
    if (LoginUser.ContainsKey(userId))
                
    {
                    DeleteUser(userId);
                    AddUser(userId, newGuid);
                }

            }


            
    public static string GetGuid(string userId)
            
    {
                
    if (LoginUser.ContainsKey(userId))
                
    {
                    
    return LoginUser[userId].ToString();
                }

                
    else
                    
    return null;
            }


            
    public static bool ContainKey(string userId)
            
    {
                
    return LoginUser.ContainsKey(userId);
            }


            
    public static UserStatus GetUserStatus(string userId, string guid)
            
    {
                
    if (LoginUser.ContainsKey(userId))
                
    {
                    
    if (guid == LoginUser[userId].ToString())
                    
    {
                        
    return UserStatus.Usual;
                    }

                    
    else
                    
    {
                        
    return UserStatus.Change;
                    }

                }

                
    else
                
    {
                    
    return UserStatus.NoUser;
                }

            }

        }

    2. 添加一个专门用于检测用户状态的页面userstatus.aspx

    protected void Page_Load(object sender, EventArgs e)
        
    {
            Response.ClearContent();
            Response.Write(getUserStatus());
            Response.End();
        }


        
    private string getUserStatus()
        
    {
            
    string returnString = "Usual";
            
    if (Session["UserID"!= null && Session["Guid"!= null)
            
    {
                UserCollection.UserStatus status 
    = UserCollection.GetUserStatus(Session["UserID"].ToString(), Session["Guid"].ToString());
                
    if (status == UserCollection.UserStatus.Change)
                
    {
                    UserCollection.LogOff(Session[
    "UserID"].ToString(), Session["Guid"].ToString());
                    Session.Clear();
                    returnString 
    = "LogOff";
                }

                
    else
                
    {
                    returnString 
    = "Usual";
                }

            }

            
    else
                Response.Redirect(
    "../Login.aspx");
            
    return returnString;
        }

    3.添加JS文件header.js,使用AJAX的机制来调用userstatus.aspx以检测用户的登陆信息

    var xmlhttp;

    function header()
    {
        var url
    ="../UserStatus.aspx?dd=" + getRandom();    
        
    if (window.XMLHttpRequest)        {
              xmlhttp
    =new XMLHttpRequest();
            xmlhttp.onreadystatechange
    =xmlhttpChange;
            xmlhttp.open(
    "GET",url,false);
            xmlhttp.send(
    null);        
        }

        
    else if (window.ActiveXObject)        {
              xmlhttp
    =new ActiveXObject("Microsoft.XMLHTTP")
                
    if (xmlhttp)
            
    {
                xmlhttp.onreadystatechange
    =xmlhttpChange;
                xmlhttp.open(
    "GET",url,false);
                xmlhttp.send();
            }

          }

        var text 
    = xmlhttp.responseText;
          
    if(text=="LogOff")
          
    {    document.location.href="../Login.aspx";
          }

        xmlhttp 
    = null;
    }
        

    function getRandom()
    {
        var ran_number
    = Math.random()*5
        
    return ran_number;
    }


    function xmlhttpChange()
    {
        
    if (xmlhttp.readyState==4)
        
    {
            
    if (xmlhttp.status==200)
            
    {
                
    // some code here
            }

            
    else
            
    {
                
    //alert("Problem retrieving XML data")
            }

        }

    }


    4.让系统的webmaster或者类似页面每10检测一次用户的登陆信息

    <script language="JavaScript" src="../JS/header.js"></script>

    <script language="javascript">
            waitTime
    =10000//10 秒
            timer=setInterval("header()",waitTime);         
    </script>

     至此系统可以实现后单点登陆.

  • 相关阅读:
    AGC003E
    Vegetable's Refrain
    error C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _stricmp.
    给linux shell 添加ll命令支持
    编译WDF驱动项目时,缺少WDKConversionPreConfiguration.props文件的问题
    idea报错:Please, configure Web Facet first!以及打开网页后出现:HTTP状态 404
    php安装gd库
    Shell下实现免密码快速登陆MySQL数据库的方法
    mysql命令导入百万数据
    java 两个数字相除后保留小数点
  • 原文地址:https://www.cnblogs.com/happlyonline/p/806000.html
Copyright © 2020-2023  润新知