單點登陸系統,簡稱SSO。如下是我花了幾個小時寫的一個簡單實現。特把實現思路和你們分享。git
背景:某項目使用ASP.NET MemberShip來作會員系統,須要同時登陸多個系統。而項目的開發人員沒法在MemberShip基礎上作單點登陸。github
故這個單點登陸系統須要能無縫集成到這些系統中的任何系統中,做爲服務端。數據庫
下面咱們來看看具體的實現步驟,沒耐心看完的朋友可直接上github上查閱:(https://github.com/newmin/cms/blob/master/extend/Ops.Cms.Extend/SSO/):session
一. 定義SSO的主要方法:url
1. 客戶端須要包含:登陸,登出,獲取會話spa
1 using System; 2 using System.Web; 3 using Ops.Cms.Extend.SSO; 4 5 namespace Ops.Cms.Extend.SSO.Client 6 { 7 public interface ISessionClient 8 { 9 /// <summary> 10 /// 處理SSO請求 11 /// </summary> 12 /// <param name="context"></param> 13 void HandleSsoRequest(HttpContext context); 14 15 /// <summary> 16 /// 獲取會話 17 /// </summary> 18 /// <param name="sessionKey"></param> 19 /// <returns></returns> 20 SessionResult GetSession(String sessionKey); 21 22 /// <summary> 23 /// 獲取會話Key 24 /// </summary> 25 /// <returns></returns> 26 String GetSessionKey(); 27 28 /// <summary> 29 /// 同步登錄 30 /// </summary> 31 /// <param name="user"></param> 32 /// <param name="pwd"></param> 33 /// <returns></returns> 34 SsoResult Login(String user, String pwd); 35 36 /// <summary> 37 /// 同步登出 38 /// </summary> 39 /// <param name="sessionKey"></param> 40 /// <returns></returns> 41 SsoResult Logout(String sessionKey); 42 } 43 }
2. 服務端須要處理客戶端的請求,同時包含會話的管理,以及客戶端的註冊code
using System; using System.Collections.Generic; using System.Text; using System.Web; using Ops.Framework.Extensions; namespace Ops.Cms.Extend.SSO.Server { public class SessionServer { /// <summary> /// 註冊客戶端 /// </summary> /// <param name="url"></param> public void RegisterClient(String url) /// <summary> /// 會話管理 /// </summary> public SessionManager SessionManager /// <summary> /// 會話服務響應 /// </summary> public String Process(HttpContext context) /// <summary> /// 登錄 /// </summary> /// <param name="usr"></param> /// <param name="pwd"></param> /// <returns></returns> private SsoResult Login(string usr, string pwd) /// <summary> /// 退出登錄 /// </summary> /// <param name="sessionKey"></param> /// <returns></returns> private SsoResult LoginOut(string sessionKey) } }
2.1 客戶端註冊server
將客戶端註冊,在返回登陸/登出結果的時候,會請求全部客戶端,以實現同步。blog
2.2 會話管理接口
須要存儲會員和會話鍵之間的關係,在這個實現中我使用了KV數據庫,LevelDb來支持。
同時定義了ISessionSet,意味着能夠使用任何方式來存儲會話,只要實現了ISessionSet接口
ISessionSet.cs
namespace Ops.Cms.Extend.SSO { /// <summary> /// 會話數據集合 /// </summary> public interface ISessionSet { /// <summary> /// 更新會話信息 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns>返回以前的會話信息</returns> string Put(string key, string value); /// <summary> /// 刪除會話信息 /// </summary> /// <param name="key"></param> void Delete(string key); /// <summary> /// 獲取會話信息 /// </summary> /// <param name="key"></param> string Get(string key); } }
三。驗證會員
由於會員不存在於此SSO中,故定義了委託,在初始化服務端時,傳入委託便可。
namespace Ops.Cms.Extend.SSO { /// <summary> /// 登錄處理 /// </summary> /// <param name="usr"></param> /// <param name="pwd"></param> /// <returns>返回personId</returns> public delegate int SSOLoginHandler(string usr,string pwd); }
委託返回int值,爲會員的編號,因此咱們還須要定義一個獲取會員信息的委託
namespace Ops.Cms.Extend.SSO { /// <summary> /// 人員獲取處理事件 /// </summary> /// <param name="personId"></param> /// <returns></returns> public delegate Person PersonFetchHandler(int personId); }
四. 啓動服務端
至此,咱們已經完成了基本實現。
PS: 很久沒有發博客了,好辛苦。直接附上DEMO:
https://github.com/newmin/cms/blob/master/extend/Ops.Cms.Extend/SSO/Demo/server.ashx.cs