zoukankan      html  css  js  c++  java
  • 单点登陆 ---密钥

    一、需求描述

    现在有A系统和B系统,需要在A系统进行单点登陆到B系统。

    二、B系统要做事

    1、提供一个可以让A系统登陆的网址

    http://localhost:8083/Account/SingleSignOn/?u=xxx&token=FB92B341DBDB59D7

    其中,u为加密后的用户名,token为B系统与A系统单点登录握手密钥

    2、控制器中的方法代码如下

    [AllowAnonymous]
            [NoTransaction]
            /// <summary>
            /// 执行单点登录
            /// </summary>
            public ActionResult SingleSignOn()
            {
                RedirectToRouteResult result = null;
                string usertokenString = Request.Params["token"];
                string userName = Request.Params["u"];
                string loginname = DESHelper.Decrypt(userName);
                string token = System.Configuration.ConfigurationSettings.AppSettings["token"];
                if (!string.IsNullOrEmpty(usertokenString))
                {
                    if (usertokenString != token || string.IsNullOrEmpty(userName))
                    {
                        result = RedirectToAction("NotRole", "Home");
                    }
                    else
                    {
                        MembershipUser user = Membership.GetUser(loginname, false);
                        if (user == null)
                        {
                            //用户不存在
                            result = RedirectToAction("UserNotExist", "Home");
                        }
                        else if (user.IsLockedOut)
                        {
                            //用户被锁定
                            result = RedirectToAction("UserIsLockedOut", "Home");
                        }
                        else if (!user.IsApproved)
                        {
                            //用户未启用 
                            result = RedirectToAction("UserIsApproved", "Home");
                        }
                        else
                        {
                            LogInfoService lis = new LogInfoService();
                            LogInfo lilist = new LogInfo(ProfileHelper.GetName(), "登录", "登录");
                            lis.Save(lilist);
                            result = RedirectToAction("Index", "Member");
                        }
                    }
                }
                else
                    result = RedirectToAction("NotRole", "Home");
    
                Session["userid"] = loginname;
                System.Web.Security.FormsAuthentication.SetAuthCookie(loginname, true);
                return result;
            }

    首先我们要接过传过来的token和用户名u,

    其次我们要对用户名进行解密

    最后我们要比较token是不是A系统认证的token,并查找用户名是否存在

    如果都满足则让用户登陆

    3、解密用户名,要步骤2中,要对传过来的用户名进行解密,加密解决的方法都提供了

    /// <summary>
        /// DES对称加密
        /// </summary>
        public static class DESHelper
        {
            /// <summary>
            /// 根据用户名解密
            /// </summary>
            /// <param name="val"></param>
            /// <param name="userid"></param>
            /// <returns></returns>
            public static string Decrypt(string val, string userid = "")
            {
    
                var key = GetKey(userid);
                var iv = GetDefaultIV();
                return Decrypt(val, key, iv);
            }
    
            /// <summary>
            /// 根据用户名加密
            /// </summary>
            /// <param name="val"></param>
            /// <param name="userid"></param>
            /// <returns></returns>
            public static string Encrypt(string val, string userid = "")
            {
    
                var key = GetKey(userid);
                var iv = GetDefaultIV();
                return Encrypt(val, key, iv);
            }
    
            /// <summary>
            /// Des加密方法
            /// </summary>
            /// <param name="val"></param>
            /// <param name="key"></param>
            /// <param name="IV"></param>
            /// <returns></returns>
            public static string Encrypt(string val, string key, string IV, CipherMode cipherMode = CipherMode.ECB)
            {
                try
                {
                    if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(key))
                    {
                        throw new Exception("密钥和偏移向量不足8位");
                    }
    
                    if (key.Length > 8) key = key.Substring(0, 8);
                    if (IV.Length > 8) IV = IV.Substring(0, 8);
    
                    DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                    byte[] btKey = Encoding.Default.GetBytes(key);
                    byte[] btIV = Encoding.Default.GetBytes(IV);
                    StringBuilder builder = new StringBuilder();
                    using (MemoryStream ms = new MemoryStream())
                    {
                        byte[] inData = Encoding.Default.GetBytes(val);
                        using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                        {
                            cs.Write(inData, 0, inData.Length);
                            cs.FlushFinalBlock();
                        }
    
                        foreach (byte num in ms.ToArray())
                        {
                            builder.AppendFormat("{0:X2}", num);
                        }
                    } 
                    return builder.ToString();
                }
                catch // (Exception ex)
                {
                    return "";
                }
            }
    
            /// <summary>
            /// Des解密方法
            /// cbc模式:(key值和iv值一致)
            /// </summary>
            /// <param name="val"></param>
            /// <param name="key"></param>
            /// <param name="IV"></param>
            /// <returns></returns>
            public static string Decrypt(string val, string key, string IV, CipherMode cipherMode = CipherMode.ECB)
            {
                try
                {
                    if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(key))
                    {
                        throw new Exception("密钥和偏移向量不足8位");
                    }
    
                    if (key.Length > 8) key = key.Substring(0, 8);
                    if (IV.Length > 8) IV = IV.Substring(0, 8);
    
                    DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                    byte[] btKey = Encoding.Default.GetBytes(key);
                    byte[] btIV = Encoding.Default.GetBytes(IV);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        byte[] inData = new byte[val.Length / 2];
                        for (int i = 0; i < (val.Length / 2); i++)
                        {
                            int num2 = Convert.ToInt32(val.Substring(i * 2, 2), 0x10);
                            inData[i] = (byte)num2;
                        }
    
                        using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                        {
                            cs.Write(inData, 0, inData.Length);
                            cs.FlushFinalBlock();
                        }
    
                        return Encoding.Default.GetString(ms.ToArray());
                    }
                }
                catch // (System.Exception ex)
                {
                    return "";
                }
            }
    
            /// <summary>
            /// Md5加密
            /// </summary>
            /// <param name="str"></param>
            /// <returns></returns>
            public static string MD5(string str)
            {
                if (string.IsNullOrEmpty(str)) return str;
                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
                string encoded = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(str))).Replace("-", "");
                return encoded;
            }
    
            private static string GetKey(string key)
            {
                string defaultKey = "C560F02F693B4A0BA62D2B3B5FB74534";
                string sTemp = defaultKey;
                if (!string.IsNullOrEmpty(key))
                {
                    sTemp = string.Concat(key, defaultKey.Substring(key.Length, 32 - key.Length));
                }
                return MD5(sTemp).Substring(0, 8);
            }
            /// <summary>   
            /// 获得初始向量IV 
            /// </summary>   
            /// <returns>初试向量IV</returns>   
            private static string GetDefaultIV()
            {
                string sTemp = "87DE696F56DE49C0B96EB85139A48805";
                return MD5(sTemp).Substring(0, 8);
            }
        }

    三、A系统要做的事

    1、直接访问B提供的网址

    http://localhost:8083/Account/SingleSignOn/?token=FB92B341DBDB59D7&u="+userName

    其中用户名userName是进行加密了的

    2、加密用户名的方法

    public string GetUserId()
            {
               return Encrypt(HttpContext.Current.User.Identity.Name);
            }
    
            public string Encrypt(string val)
            {
                var key = "87DE696F";//测试期间请用此key使用
                try
                {
                    DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                    byte[] btKey = Encoding.Default.GetBytes(key);
                    byte[] btIV = Encoding.Default.GetBytes(key);
                    StringBuilder builder = new StringBuilder();
                    using (MemoryStream ms = new MemoryStream())
                    {
                        byte[] inData = Encoding.Default.GetBytes(val);
                        using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                        {
                            cs.Write(inData, 0, inData.Length);
                            cs.FlushFinalBlock();
                        }
    
                        foreach (byte num in ms.ToArray())
                        {
                            builder.AppendFormat("{0:x2}", num);
                        }
                    }
                    return builder.ToString();
                }
                catch // (Exception ex)
                {
                    return "";
                }
            }
  • 相关阅读:
    在编码转错的情况下,如何恢复
    【娱乐】给你的电脑检查兼容性,并获取你的电脑上安装的软件
    发布一个纯PHP的中文关键字自动提取工具
    [转]程序员能力矩阵 Programmer Competency Matrix
    解决PHP数组内存耗用太多的问题
    哈希表之数学原理
    PHP高级编程之单线程实现并行抓取网页
    如何自动的检测字符串编码
    如何检测网络中断, 并自动重启网卡
    完全二叉树判断,简单而复杂
  • 原文地址:https://www.cnblogs.com/zhengwei-cq/p/10316307.html
Copyright © 2011-2022 走看看