自從上次的《偷懶小工具 - Excel導出》發佈之後,看閱讀量還能夠,就決定繼續分享一下其餘方面的幫助類。html
風格仍是相似的極簡風,登陸方法,調用的代碼儘可能超過三行,而後搞定一切。源代碼參考文章最下方。git
a.baidu.com 中。a 是二級域名,baidu 是一級域名。一樣的一級域名是能夠共享Cookie的。github
不一樣一級域名,由於同源策略緣由,不能共享Cookie。也就是跨域算法
例如:微信掃碼登陸,就是這種跨域的實用例子跨域
a.baidu.com 和 b.baidu.com 是能夠共享cookie,也就是同域。緩存
www.baidu.com 和 www.qq.com 就屬於跨域。安全
SSO 單點登陸,主要就是使用統一的身份驗證模塊,而後各網站共享身份驗證。微信
也就是隻登陸一次,其餘網站都可免登錄。cookie
關於身份驗證方面,各位若有疑惑可自行百度。或者看一下,我記錄的 《ASP.NET身份認證》函數
(是給本身看的可能有些亂)
由於同源策略的問題,因此同域和跨域方法實現差距比較大。
我這邊根據同域和跨域,這兩種不一樣狀況,分享兩個幫助類。
這兩個幫助類,互相獨立。各位按照本身的需求選擇查看使用。
(由於就一我的精力有限,白天還要上班,沒有進行太多測試)設計不合理或者BUG,確定會有一些。
首先,看一下同域的流程圖。
再看一下,跨域的流程圖
看着,很簡單吧。我相信大家確定能夠看懂,我就不做解釋了。下面看使用。
這裏WebConfig,採用了以下的配置。
用戶認證網站,直接使用~/Login.aspx 指向本身的登陸頁面。
其餘網站,使用 「認證網站地址」+?link+「本網站地址」。這種方式,來進行登陸後的跳轉。
共同一級域名的狀況。可使用SSOGeneralSameDomain類,進行登陸。
其中,Login就是用戶登陸方法。一共兩行代碼。name 參數是你須要保存的數據。
其中,Index方法,能夠得到你保存的用戶名。(這裏爲了方便使用的明文用戶名)
WebForm登陸方式是同樣的,這裏不作過多描述。
調用 SSOGeneralSameDomain.LogUp(); 可進行用戶註銷。
此時你的網站,就能夠共享身份驗證了。
不一樣一級域名的狀況。可使用SSOGeneralCrossDomain類,進行登陸
須要傳遞:保存的數據、Cookie名稱、保存時長
須要傳遞:認證網站地址、Cookie名稱、保存時長
此時,你就能夠完成跨域單點登陸了。可是注意,認證網站,還須要調用一個驗證方法。
分析
同域的思路比較簡單,也相對來講比較好實現。有兩點要考慮的(若是有其餘辦法,請留言)
Request 操做:由於Mvc和WebForm的Request,存在於兩個不一樣的類(HttpContextBase和Page)。
這個找了半天,也沒有想到能公用的辦法,因而就用抽象工廠來搞了一下。
跳轉問題:由於Forms身份認證的ReturnUrl參數,只能拿到文件,而不能拿到網址。因此無法跳轉到對應網站。
這個我在博問上試着問了一下,結果有一個大哥說:你要這麼多幹啥,沒啥用。當時我就懵逼了!!!
後來,沒有找到什麼好辦法,就用的笨辦法,也就是使用link進行跳轉。
作法
這兩個問題解決了,咱們接下來看看代碼。仍是向上次同樣,一步一步來講一下。
作Request和Response操做封裝
首先,建立一個抽象類,而後把須要的方法封裝一下,接着定義Page和HttpContext兩個子類,繼承實現
作同域單點登陸的類
1. 首先,分析一下每一個登陸,都須要名字和過時時間,那麼這倆字段上移。 確定都得有登陸方法,那麼方法上移。
這裏字段Set 私有,也是安全性的考慮。我在初始化的時候,就傳遞這兩個參數。
2. 接着,建立 SSOGeneralSameDomain 類,繼承抽象類。
定義私有字段,Operation用來執行操做。構造函數中對這個字段進行賦值。
實現抽象類的LogIn方法。這個方法只有三步:1.建立Forms認證票據。2.保存到Cookie中。3.成功後跳轉。
CreateTicket 和 CreateCookie 方法邏輯很是簡單,我就不說明了。說一下跳轉邏輯。
有link 找link,沒有找ReturnUrl,再沒有直接跳轉到根目錄。 至此登陸作完了。
3. 最後,作註銷和獲取內容方法。這邊爲了方便,使用靜態類實現的。
註銷都是固定的方法,獲取內容,就是拿Cookies。而後解密
同域的幫助類,至此就算完成了。
跨域真的是比較糾結的一點,由於我懶,因此通常都是先上網找相關文章。
發現,文章有用的很是少。一些僞跨域的特別多,有些卡卡卡說一大堆,結果發現不一樣的是二級域名。
還有就是使用 接口,來回傳信息的。由於我想作幫助類,用接口的話就耦合在一塊兒了。不太想用。
PS:找了一天,最後煩躁了不找了,開始本身想本身研究。
分析
實際上同域須要處理的地方,就是傳遞憑證。接收到憑證之後,就會進行本地存儲,因此傳遞是終點。
跨域須要考慮的點,就比較多了,除了同域的問題還有如下幾點:(若是有其餘辦法,請留言)
Cookie不能共享:使用Token做爲憑據傳遞,可根據Token獲取保存信息。
持久化:提供持久化接口,任何方式只要知足此接口便可。我這裏提供了Http緩存和Cookies方法。
登陸和認證:流程跟上面的圖差很少。主要開放五個方法:
LogIn(登陸)、LogInClient(其餘網站登陸)、ValidationToken(認證)、GetUserData(獲取登陸內容)、LogUp(註銷)
作法
1. 首先,仍是跟同域同樣作Operation 而後Page 和 HttpContextBase繼承這個Operation
2. 由於會有憑證的傳遞,因此咱們還須要一個加密。這裏,我給出一個接口,並給出了DES加密的實現方法。
各位能夠按照本身想進行的加密邏輯,自行擴展。
3. 持久層也是必不可少的,用來存放已經登陸的用戶信息。這裏也是給出的接口。並給出了Cookie 和 Cache的操做方法
各位能夠按照本身想實現的持久層,進行處理。
CreateToken 生成憑證的這個方法。我這邊採用最簡單的GUID進行生成的,這種無規律的是沒有辦法僞造的。
SetToken的UserData,使用的就是上方的加密認證。
我以爲只要涉及到HTTP傳遞,就確定能攔截,因此重點應該是怎麼不讓他破解。加密算法,各位能夠自行實現。
public class SSOToken
{
public string UserData { get; set; } public string Token { get; set; } public DateTime OverdueTime { get; set; } }
持久層存儲模型,就使用這個必不可少的幾個字段進行存儲。
4. 跨域單點登陸類,由於這個類比較複雜,因此我不想提太多公共方法或字段。
建立SSOGeneralCrossDomain類,咱們把參數都做爲屬性提出來,而後把接口也進行提取。
咱們看一下LogIn 登陸方法是如何實現的。
這個方法,是認證中心點擊保存之後執行的方法。
先進行SetToken 把登陸信息存到持久層。而後返回對應的Token。
接着進行GetRedirectUrl。這個方法獲取咱們登陸成功後,將要跳轉的地址。
接下來的,跟同域的狀況同樣。這裏就很少說了。咱們如今已經實現了,認證中心的登陸。接下來,咱們製做其餘網站的登陸。
其餘網站,使用此功能,也要定義本身的Login.aspx頁面,只是在這個頁面調用這個方法。
咱們先判斷,是登陸仍是認證。好比:咱們沒有登陸,打開網站A,這種狀況就是登陸。網站A登陸後,跳轉到網站B,這種狀況就是認證
接下來咱們驗證Token,這一步很重要。這一步能夠把網站引導到認證中心,或者自動認證。
接下來,就是顯而易見的 解密、本地存儲了。很簡單很少講了。
GetUserData 和 LogUp。一個是獲取本地Cookie,一個是註銷登陸(跟同域操做同樣)
至此,咱們的單點登陸,所有搞定。接下來,咱們進行測試。
首先,咱們建立兩個認證中心。一個MVC的,一個WebForm的。而後Web建立2個網站,MVC建立1個。用來作跳轉。
Authorize 認證中心,使用的是MVP 的PV模式。首先咱們給Web相關的網站,定義統一的Web.Config
同域狀況下,Web1\2 登陸地址均指向 Authorize
接下來,在登陸後調用方法
咱們在 Web1 裏面寫一下獲取方法 和 註銷
這個時候,咱們Web1設爲啓動項。而後就能夠測試了。具體頁面,我就不粘貼了。能夠參考下方源碼
跨域須要在各個應用底下,建立本身的Login.aspx登陸頁面。而後調用這個方法,或者你建立主頁調用同樣。
Web1網站 調用方法以下
加載內容以下
Authorize網站,調用方法以下
在Initialize 初始化的時候,添加驗證方法。這樣能夠接受其餘網站發送的驗證請求。
在登陸頁面,直接調用登陸方法便可。
具體測試項目,都在Github上。各位能夠自行下載。