sso 登錄,網頁跳轉的實現方式


sso 登錄,網頁跳轉的實現方式

在昨天的博客中http://www.cnblogs.com/jake1/archive/2013/04/28/sso_scheme.html,我們介紹了幾種單點登錄的方案.不過那些方案我都沒有實現過,只是在自己的一些客戶公司里見過,下面我就要親自介紹,我親身設計和參與的sso方案.

  首先,我們看看設計圖吧.

注:1)紅色部分為加密傳送的內容;

    2)綠色部分為門戶系統實現的流程;

    3)灰色部分為外部應用系統原有已經實現的流程;

    4)藍色部分為外部應用系統需要增加或修改的流程;

 

針對上面的圖:流程看如下解釋.

 

  • 場景一.用戶從門戶單點登錄進入外部應用系統(參看流程圖Step1、Step2

Step1

1)   用戶在瀏覽器輸入門戶的地址進入門戶系統;

2)   用戶輸入門戶系統的用戶名和密碼;

3)   認證中心向AD發起登錄認證;

4)   AD認證失敗返回門戶系統的登錄頁面,系統記錄日志並提示錯誤信息;AD認證成功,門戶系統登錄成功轉到步驟6);

5)   用戶重新輸入門戶系統的用戶名和密碼,返回步驟3)重新登錄;

6)        門戶系統登錄成功跳轉到登錄來源頁,如果沒有登錄來源頁跳轉到門戶系統首頁;

Step2

1)   用戶在門戶系統的頁面,點擊外部應用系統的鏈接,進行單點登錄流程;

2)   門戶系統先判斷門戶登錄憑證是否失效;

3)   門戶系統登錄憑證失效返回Step1的 門戶系統登錄流程;

4)   門戶系統登錄憑證沒有失效,判斷單點登錄的系統是否是集成AD;

5)   集成AD登錄的系統直接獲取當前用戶名和密碼;

6)   沒有集成AD登錄的系統,通過用戶映射關系獲取外部應用系統的用戶名和密碼;

7)   如果不存在對應的外部應用系統的用戶映射關系(沒有做初始化外部應用系統的用戶映射關系情況),彈出單點登錄映射信息填寫頁,用戶填寫外部應用系統的用戶名和密碼;

8)   如果存在對應的外部應用系統的用戶映射關系,獲取外部應用系統的用戶名和密碼;

9)   對用戶填寫的外部應用系統的用戶名和密碼,門戶需要記錄;

10) 把外部應用系統的用戶名和密碼加密(對稱加密)(分別按門戶系統與外部接入系統約定方式進行加密解密);

11) 把加密后的用戶名和密碼以參數形式傳遞給外部應有系統(外部應用系統需要實現接受用戶名和密碼的接口);

12) 外部應用系統先運行原有的登錄認證流程,發現在原有認證流程無法使系統登錄的時候,從參數讀取用戶憑證,也不存在調用門戶系統登錄請求接口;

13) 能獲取用戶憑證,對用戶憑證進行解密(分別按門戶系統與外部接入系統約定方式進行加密解密);

14) 使用用戶憑證進行外部應用系統的登錄認證;

15) 認證成功轉到外部應用系統頁面,並調用門戶記錄日志

16) 認證失敗調用門戶系統登錄請求接口

17) 調用門戶登錄請求會重新執行步驟2);

  • 場景二.用戶在瀏覽器直接進入外部應用系統(參看流程圖Step3

Step3

1)   用戶在瀏覽器直接輸入外部應用系統的地址;

2)   外部應用系統實現的流程和Step2的步驟12)一致,先實現外部應有系統的登錄認證流程,若沒有不能登錄系統,讀取參數,都讀取不到用戶憑證向門戶系統發出登錄請求(參看接口3.6.2),若能讀取對用戶憑證解密,進行外部應用系統的認證登錄;

3)   認證成功轉到外部應用系統頁面,並調用門戶記錄日志

4)   認證失敗調用門戶系統登錄請求接口

   這方案的優點是可以實現雙向登錄,而且針對所有web站點都可以實現單點登錄..缺點是實現比較復雜,而且需要更改其他系統.

   至於代部分碼我將會在接下來的博客中介紹.敬請各位關注.

 

C#后台調用跨域MVC服務,帶Cookie驗證

 
背景

隨着富客戶端框架的盛行,以及眾多優秀的前端js框架,很多情況我們會遇到跨域的問題,而js的ajax請求是不允許直接跨域訪問的,當然你會說可以用JSONP等,但是由於代碼潔癖,不想在前端和后台添加callback,而且很多情況你是無法控制的,需要牽連考慮太多的情況。

所以我直接繞過了,每個前端應用,自帶一個通用后端服務代理,該服務解決跨域問題,自動代理幫前台獲取跨域的數據。 

如何算跨域

雖然是個老問題,但是還是要提醒注意下兩點:同IP,不同端口,數據訪問是跨域的,但是Cookie訪問是可以的(這個讓我很難理解)

解決,源碼
復制代碼
     CookieContainer cookieContainer = new CookieContainer();

     [HttpPost]
        public string CommonPost(string url)
        {
            log.Info(CookieHelper.GetCookie("ITDC_UserName") + "進入方法CommonPost Url=" + url);
            Uri address = new Uri(System.Configuration.ConfigurationManager.AppSettings["RESTfulAPI"].ToString() + url);
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
       //遠程服務,需要加入cookie驗證
            cookieContainer.Add(address, GetCookie("ITDC_UserName"));
            cookieContainer.Add(address, GetCookie("ITDC_UserRole"));
            request.CookieContainer = cookieContainer;
            StringBuilder data = new StringBuilder();
            for (int i = 0; i < Request.QueryString.Count; i++)
            {
                if (Request.QueryString.Keys[i].ToString() == "url") continue;
                data.Append("&" + Request.QueryString.Keys[i].ToString() + "=" + Request.QueryString[i].ToString());
            }
            // Create a byte array of the data we want to send
            byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString().TrimStart('&'));
            // Set the content length in the request headers
            request.ContentLength = byteData.Length;
            // Write data  
            using (Stream postStream = request.GetRequestStream())
            {
                postStream.Write(byteData, 0, byteData.Length);
            }  
            string result = "";
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                result = reader.ReadToEnd();
            }
            log.Info(CookieHelper.GetCookie("ITDC_UserName") + " 執行完成 CommonPost Url=" + url);
            return (result);
        }
復制代碼

前台調用

復制代碼
Ext.Ajax.request({url: APIUrl + '/Nebula/CommonPost?url=/Nebula/PostComment/&KlId=1&Msg=ok&Author=admin&Title=文章標題',
                  method: "POST",
                  success: function (response) {
                              Ext.Viewport.unmask();
                              var obj = Ext.decode(response.responseText);
                              Ext.Msg.alert("提示", obj.Msg, Ext.emptyFn);
                           },
                  failure: function (response) {
                              Ext.Viewport.unmask();
                              Ext.Msg.alert("提示", "操作失敗,請檢查網絡!", Ext.emptyFn);
                           }
});
復制代碼

 

如果您認可我的工作,並且覺得本文對您有所幫助,可以通過支付寶或轉發文章的方式資助我們,我們願意接受來自各方面的捐贈。再次感謝您對開源事業的贊助和支持!
文章部分內容可能摘自網絡,如果侵犯您的權益,請及時聯系我,謝謝.

作者:JackChain
 
 
標簽:  sso網頁跳轉


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM