1、需求描述html
如今有A系統和B系統,須要在A系統進行單點登錄到B系統。ide
2、B系統要作事post
一、提供一個可讓A系統登錄的網址測試
http://localhost:8083/Account/SingleSignOn/?u=xxx&token=FB92B341DBDB59D7ui
其中,u爲加密後的用戶名,token爲B系統與A系統單點登陸握手密鑰加密
二、控制器中的方法代碼以下spa
[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,code
其次咱們要對用戶名進行解密orm
最後咱們要比較token是否是A系統認證的token,並查找用戶名是否存在htm
若是都知足則讓用戶登錄
三、解密用戶名,要步驟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); } }
3、A系統要作的事
一、直接訪問B提供的網址
http://localhost:8083/Account/SingleSignOn/?token=FB92B341DBDB59D7&u="+userName
其中用戶名userName是進行加密了的
二、加密用戶名的方法
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 ""; } }