SSO集成方案[隨筆]

来源:https://www.cnblogs.com/sy-ds/archive/2019/04/12/10696218.html
-Advertisement-
Play Games

看這個方案之前,先說明下為什麼要加入SSO,以防對大家產生不好的影響。我們產品使用傳統winform+db服務+Db存儲方式開發,一群老菜幫子開發,以傳統的datatble做數據傳遞,很多年了未有變化。 然後我來了,感覺我這個老菜幫子都受不了這種開發,然後下定決心,作了一些封裝,看起來有點像orm的 ...


看這個方案之前,先說明下為什麼要加入SSO,以防對大家產生不好的影響。我們產品使用傳統winform+db服務+Db存儲方式開發,一群老菜幫子開發,以傳統的datatble做數據傳遞,很多年了未有變化。

然後我來了,感覺我這個老菜幫子都受不了這種開發,然後下定決心,作了一些封裝,看起來有點像orm的感覺了,並決定加入嵌入bs頁面,美化界面,並補充winform在圖表功能方面的短板。

然後就造成了各BS模塊分別嵌入到CS不同的頁面中,並且各BS模塊中有涉及到對業務的操作。很危險!因為在網頁中可以直接打開各BS模塊視圖,無需登錄,無需驗證等。針對這種情況,SSO需求由此而來…

 

目標:

  1.BS模塊統一使用單點登錄,不能沒有限制就使用業務系統

  2.CS端嵌入BS時自動模擬SSO,實現可以免登錄使用頁面

 

下文SSO科普是複製不知道誰的博文的,具體是誰忘了,在此說明下

SSO整體流程圖:

 

 

 

SSO分為SSO-ServerSSO-Client兩個部分,SSO-Client可以是多個的,即各個需要單點登錄的client

SSO-Server

SSO-Server主要負責用戶登錄、註銷、為SSO-Client分配token、驗證token的工作。

SSO-Server分配Token

為SSO-Client分配Token的部分,在SSO-Client請求SSO受信頁面的時候,檢查SSO-Server是否登錄,如果沒有登錄則跳轉到SSO-Server的登錄頁面,如果已登錄,則執行分配Token的代碼,在分配完成以後將TokenID作為參數添加到returnUrl中,並跳轉到returnUrl。

當完成Token分配之後,頁面將帶有Token的參數跳轉到SSO-Client頁面,併在SSO-Client的Cookie中添加Token值,在以後的每次請求中,SSO-Client通過調用SSO-Server的服務來驗證Token的合法性。

ValidateToken用來驗證TokenID的合法性,KeepToken用來保持Token不會過期。

SSO-Client通過調用Validate驗證Token,並得到當前的登錄用戶信息。

SSO-Client

SSO-Client作為受信系統來存在的,它自己沒有認證系統,只能通過SSO-Server來完成用戶身份認證的工作。

當用戶請求SSO-Client的受保護資源時,SSO-Client會首先是否有TokenID,如果存在TokenID,則調用SSO-Server的介面來驗證這個TokenID是否合法;

驗證成功以後將會返回SSOToken的實例,裡面包含已登錄的用戶信息

 

科普後動手:

MVC.SSO.Service:MVC+Redis,MVC實現SSO-Server的所有功能,存儲和時效使用Redis管理,並使用Redis共用Session

主要代碼:

     /// <summary>
        /// 驗證是否包含該token,並返回信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpPost]
        public string ValidateToken(string key)
        {
            //var token = TokensManager.GetToken(key);

            try
            {
                MyToken token = new MyToken();
                token.ValidateToken = false;

                if (BoolValidateToken(key))
                {
                    token.User = redis.StringGet<USERS>(key);
                    token.ValidateToken = true;
                }

                return JsonConvert.SerializeObject(token);
            }
            catch (Exception ex)
            {
                throw new Exception("ValidateToken:" + ex.Message);
            }
        }


     /// <summary>
        /// 登錄
        /// </summary>
        /// <param name="name"></param>
        /// <param name="passWord"></param>
        /// <param name="backUrl"></param>
        /// <returns></returns>
        [HttpPost]
        public string Login(string name, string passWord, string backUrl)
        {
            try
            {
                MyMsg msg = new MyMsg();
                //tokenKey
                byte[] byts = System.Text.Encoding.Default.GetBytes(string.Format("{0},{1}", name, passWord));
                var key = Convert.ToBase64String(byts);
                //判斷是否TokenIds是否已存在該用戶,不存在則判斷登錄,添加到token
                if (!BoolValidateToken(key))
                {
                    var user = userBll.GetUser(name, passWord);
                    if (user == null)
                    {
                        msg.IsLogined = false;
                        msg.Msg = "用戶名或密碼錯誤,登錄失敗!";
                    }
                    msg.IsLogined = true;
                    //並添加到全局變數中
                    //TokensManager.AddToken(key, user);
                    Session["Token"] = key;
                    redis.StringSet<USERS>(key, user);
                }

                Session["Token"] = key;
                Response.Cookies.Add(new HttpCookie("cToken", key));
                if (!string.IsNullOrEmpty(backUrl))
                {
                    var url = backUrl + "?token=" + key;
                    //Response.Redirect(backUrl + "?token=" + key, true);//生成一個tokenId 發放到客戶端
                    msg.BackUrl = url;
                }
                msg.Msg = "歡迎您:" + name;
                return JsonConvert.SerializeObject(msg);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

 

BS端MVC-Client集成方案

MVC集成SSO方式為添加過濾器,併在需要添加SSO驗證的控制器上添加上該過濾器

主要代碼:

public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);

            try
            {
                bool isLogined = false;//登錄標誌
                var cToken = filterContext.HttpContext.Request.Cookies["cToken"];
                var token = filterContext.HttpContext.Request["token"];
                var sessionKey = HttpContext.Current.Session["Token"];
                if (token != null || sessionKey != null || cToken != null)
                {//eWFuc2hpLGE=
                    token = token ?? sessionKey.ToString() ?? cToken.Value;
                    var data = new { key = token };
                    //如果token不為空則去服務驗證token是否有效
                    HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(data));
                    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    var httpClient = new HttpClient();
                    var responseJson = httpClient.PostAsync(SSOURL + "/ValidateToken", httpContent)
                        .Result.Content.ReadAsStringAsync().Result;
                    var myToken = JsonConvert.DeserializeObject<JH_OEMR_Model.MyToken>(responseJson);
                    if (myToken.ValidateToken)
                    {
                        isLogined = true;
                    }
                }

                if (!isLogined)
                    filterContext.HttpContext.Response.Redirect(SSOURL+"?backUrl=" + filterContext.HttpContext.Request.Url, true);
            }
            catch (Exception ex)
            {
                filterContext.HttpContext.Response.Write("aaaaa"+ex.Message.ToString());
                throw;
            }
        }

CS端集成SSO:

CS端載入BS頁面時,先判斷是否模擬登錄,如未登錄,模擬登錄,然後訪問BS端網址帶上token即可

主要代碼:

private static void LoginSSO()
        {
            var data = new { name = UName, passWord = UPwd, backUrl = string.Empty };
            HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(data));
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var httpClient = new HttpClient();
            var responseJson = httpClient.PostAsync(SSOURL+"/Login", httpContent)
                .Result.Content.ReadAsStringAsync().Result;
            var myToken = JsonConvert.DeserializeObject<MyMsg>(responseJson);
            if (myToken.IsLogined)
            {
                IsLoginedSSO = true;
            }
        }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天我們來說下如何在windows下使用docker運行.net core,既然是docker,那麼我們首先得在windows上安裝docker。 在Windows安裝 docker 有兩種選擇 :1、docker for windows2、docker toolbox 區別:docker for ...
  • yyyyyyyyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyy ...
  • 使用 ASP.NET Core MVC 創建 Web API 使用 ASP.NET Core MVC 創建 Web API(一) 使用 ASP.NET Core MVC 創建 Web API(二) 十、添加 GetBookItem 方法 1) 在Visual Studio 2017中的“解決方案資源 ...
  • 索引: 目錄索引 一.API 列表 1.Set<M, F>(Expression<Func<M, F>> propertyFunc, F newVal) 如: .Set(it => it.BodyMeasureProperty, "{xxx:yyy,mmm:nnn,zzz:aaa}") 用於 單表 ...
  • 今天自己開發了一個訂機票的微信公眾號,功能基本已經完成,然後想部署到伺服器實際測試下。結果部署上去出現各種問題。先安裝asp.net core模塊,然後發現資料庫並不像在開發時一樣,執行ef的命令行語句就可以了。可以到輸出目錄找到對應的sql語句,到伺服器上執行一下。 後來部署上去以後,發現很多對應... ...
  • 轉自:https://blog.csdn.net/jie_liang/article/details/77340905 用以記錄: 在sql查詢中為了提高查詢效率,我們常常會採取一些措施對查詢語句進行sql優化,下麵總結的一些方法,有需要的可以參考參考。 1.對查詢進行優化,應儘量避免全表掃描,首先 ...
  • //通過ClassName獲取div,使用setAttribute設置div禁止點擊 pointer-events: none;是css3新出現的屬性,意思就是禁止滑鼠點擊事件,當元素中有這一屬性時,鏈接、點擊事件統統失效 ...
  • 通過註解(特性)的方式進行對象的註冊與註入,方便,靈活! 本篇主要講如何去實現,下一篇主要講如何把它集成到mvc和api環境里,實現自動的註入! spring ioc工作的過程大致為,統一的註冊組件,攔截當前請求,統一的註入當前請求所需要的組件,事實上,說到這事,.net也完全可以實現這個功能和工作 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...