亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

SSO

系統 2081 0

基于.Net的單點登錄(SSO)解決方案

????? 前些天一位朋友要我幫忙做一單點登錄,其實這個概念早已耳熟能詳,但實際應用很少,難得最近輕閑,于是決定通過本文來詳細描述一個SSO解決方案,希望對 大家有所幫助。SSO的解決方案很多,但搜索結果令人大失所望,大部分是相互轉載,并且描述的也是走馬觀花。
????? 閑話少敘,進入正題,我的想法是使用集中驗證方式,多個站點集中Passport驗證。?如下圖所示:
SSO
????? 為方便清晰描述,先定義幾個名詞,本文中出現之處均為如下含義。

????? 主站 :Passport集中驗證服務器 http://www.passport.com/
????? 分站 http://www.a.com/ http://www.b.com/ http://www.c.com/ ?
?????? 憑證 :用戶登錄后產生的數據標識,用于識別授權用戶,可為多種方式,DEMO中主站我使用的是Cache,分站使用Session。
????? 令牌 :由Passport頒發可在各分站中流通的唯一標識。
????? OK,現在描述一下單點登錄的過程:
????? 情形一、匿名用戶:匿名用戶訪問分站a上的一個授權頁面,首先跳轉到主站讓用戶輸入帳號、密碼進行登錄,驗證通過后產生主站憑證,同時產生令牌,跳轉回分 站a,此時分站a檢測到用戶已持有令牌,于是用令牌再次去主站獲取用戶憑證,獲取成功后允許用戶訪問該授權頁面。同時產生分站a的本地憑證,當該用戶需要 再次驗證時將先檢查本地憑證,以減少網絡交互。
????? 情形二、在分站a登錄的用戶訪問分站b:因為用戶在分站a登錄過,已持有令牌,所以分站b會用令牌去主站獲取用戶憑證,獲取成功后允許用戶訪問授權頁面。同時產生分站b的本地憑證。
SSO

????? 設計完成后,接下來是方案實現的一些關鍵點:
????? 令牌 :令牌 由主站頒發,主站頒發令牌同時生成用戶憑證,并記錄令牌與用戶憑證之間的對應關系,以根據用戶提供的令牌響應對應的憑證;令牌要在各跨域分站中進行流通, 所以DEMO中令牌我使用主站的Cookie,并指定Cookie.Domain="passport.com"。各分站如何共享主站的Cookie?從 分站Redirect到主站頁面,然后該頁面讀取Cookie并以URL參數方式回傳即可,可在DEMO代碼中查看詳細實現,當然如果哪位有更好的令牌實 現方式也拿出來分享。

// 產生令牌
string ?tokenValue? = ?Guid.NewGuid().ToString().ToUpper();
HttpCookie?tokenCookie?
= ? new ?HttpCookie( " Token " );
tokenCookie.Values.Add(
" Value " ,?tokenValue);
tokenCookie.Domain?
= ? " passport.com " ;
Response.AppendCookie(tokenCookie);?


????? 主站憑證
:主站憑證是一個關系表,包含了三個字段:令牌、憑證數據、過期時間。有多種實現方式可供選擇,要求可靠的話用數據庫,要求性能的話用Cache,DEMO中我使用的是Cache中的DataTable。如下代碼所示:

/// ? <summary>
/// ?初始化數據結構
/// ? </summary>
/// ? <remarks>
/// ?----------------------------------------------------
/// ?|?token(令牌)?|?info(用戶憑證)?|?timeout(過期時間)?|
/// ?|--------------------------------------------------|
/// ? </remarks>
private ? static ? void ?cacheInit()
{
????
if ?(HttpContext.Current.Cache[ " CERT " ]? == ? null )
????{
????????DataTable?dt?
= ? new ?DataTable();

????????dt.Columns.Add(
" token " ,?Type.GetType( " System.String " ));
????????dt.Columns[
" token " ].Unique? = ? true ;

????????dt.Columns.Add(
" info " ,?Type.GetType( " System.Object " ));
????????dt.Columns[
" info " ].DefaultValue? = ? null ;

????????dt.Columns.Add(
" timeout " ,?Type.GetType( " System.DateTime " ));
????????dt.Columns[
" timeout " ].DefaultValue? = ?DateTime.Now.AddMinutes( double .Parse(System.Configuration.ConfigurationManager.AppSettings[ " timeout " ]));

????????DataColumn[]?keys?
= ? new ?DataColumn[ 1 ];
????????keys[
0 ]? = ?dt.Columns[ " token " ];
????????dt.PrimaryKey?
= ?keys;

????????
// Cache的過期時間為?令牌過期時間*2
????????HttpContext.Current.Cache.Insert( " CERT " ,?dt,? null ,?DateTime.MaxValue,?TimeSpan.FromMinutes( double .Parse(System.Configuration.ConfigurationManager.AppSettings[ " timeout " ])? * ? 2 ));
????}
}

?

????? 分站憑證 :分站憑證主要用于減少重復驗證時網絡的交互,比如用戶已在分站a上登錄過,當他再次訪問分站a時,就不必使用令牌去主站驗證了,因為分站a已有該用戶的憑證。分站憑證相對比較簡單,使用Session、Cookie均可。

????? 分站SSO頁面基類 :分站使用SSO的頁面會做一系列的邏輯判斷處理,如文章開頭的流程圖。如果有多個頁面的話不可能為每個頁寫一個這樣的邏輯,OK,那么把這套邏輯封裝成一個基類,凡是要使用SSO的頁面繼承該基類即可。如下代碼所示:

using ?System;
using ?System.Data;
using ?System.Configuration;
using ?System.Web;
using ?System.Web.Security;
using ?System.Web.UI;
using ?System.Web.UI.WebControls;
using ?System.Web.UI.WebControls.WebParts;
using ?System.Web.UI.HtmlControls;
using ?System.Text.RegularExpressions;

namespace ?SSO.SiteA.Class
{
????
/// ? <summary>
????
/// ?授權頁面基類
????
/// ? </summary>
???? public ? class ?AuthBase?:?System.Web.UI.Page
????{
????????
protected ? override ? void ?OnLoad(EventArgs?e)
????????{
????????????
if ?(Session[ " Token " ]? != ? null )
????????????{
????????????????
// 分站憑證存在
????????????????Response.Write( " 恭喜,分站憑證存在,您被授權訪問該頁面! " );
????????????}
????????????
else
????????????{
????????????????
// 令牌驗證結果
???????????????? if ?(Request.QueryString[ " Token " ]? != ? null )
????????????????{
????????????????????
if ?(Request.QueryString[ " Token " ]? != ? " $Token$ " )
????????????????????{
????????????????????????
// 持有令牌
???????????????????????? string ?tokenValue? = ?Request.QueryString[ " Token " ];
????????????????????????
// 調用WebService獲取主站憑證
????????????????????????SSO.SiteA.RefPassport.TokenService?tokenService? = ? new ?SSO.SiteA.RefPassport.TokenService();
????????????????????????
object ?o? = ?tokenService.TokenGetCredence(tokenValue);
????????????????????????
if ?(o? != ? null )
????????????????????????{
????????????????????????????
// 令牌正確
????????????????????????????Session[ " Token " ]? = ?o;
????????????????????????????Response.Write(
" 恭喜,令牌存在,您被授權訪問該頁面! " );
????????????????????????}
????????????????????????
else
????????????????????????{
????????????????????????????
// 令牌錯誤
????????????????????????????Response.Redirect( this .replaceToken());
????????????????????????}
????????????????????}
????????????????????
else
????????????????????{
????????????????????????
// 未持有令牌
????????????????????????Response.Redirect( this .replaceToken());
????????????????????}
????????????????}
????????????????
// 未進行令牌驗證,去主站驗證
???????????????? else
????????????????{
????????????????????Response.Redirect(
this .getTokenURL());
????????????????}
????????????}

????????????
base .OnLoad(e);
????????}

????????
/// ? <summary>
????????
/// ?獲取帶令牌請求的URL
????????
/// ?在當前URL中附加上令牌請求參數
????????
/// ? </summary>
????????
/// ? <returns></returns>
???????? private ? string ?getTokenURL()
????????{
????????????
string ?url? = ?Request.Url.AbsoluteUri;
????????????Regex?reg?
= ? new ?Regex( @" ^.*\?.+=.+$ " );
????????????
if ?(reg.IsMatch(url))
????????????????url?
+= ? " &Token=$Token$ " ;
????????????
else
????????????????url?
+= ? " ?Token=$Token$ " ;

????????????
return ? " http://www.passport.com/gettoken.aspx?BackURL= " ? + ?Server.UrlEncode(url);
????????}

????????
/// ? <summary>
????????
/// ?去掉URL中的令牌
????????
/// ?在當前URL中去掉令牌參數
????????
/// ? </summary>
????????
/// ? <returns></returns>
???????? private ? string ?replaceToken()
????????{
????????????
string ?url? = ?Request.Url.AbsoluteUri;
????????????url?
= ?Regex.Replace(url,? @" (\?|&)Token=.* " ,? "" ,?RegexOptions.IgnoreCase);
????????????
return ? " http://www.passport.com/userlogin.aspx?BackURL= " ? + ?Server.UrlEncode(url);
????????}

????}
// end?class
}

?

????? 用戶退出: 用戶退出時分別清空主站憑證與當前分站憑證。如果要求A站點退出,B、C站點也退出,可自行擴展接口清空每個分站憑證。
????? 主站過期憑證/令牌清除 :定時清除(DataTable)Cache[“CERT”]中timeout字段超過當前時間的記錄。

點擊此處下載DEMO

1. IIS 中配置站點

配置 4 個站點指向相應的目錄,并分別指定 4 個站點的主機頭:

http://www.passport.com/

http://www.a.com/

http://www.b.com/

http://www.c.com/ ?

2. 修改 hosts 文件以將域名解析到本地站點

127.0.0.1????????? http://www.passport.com/

127.0.0.1 ????????? http://www.a.com/

127.0.0.1 ???????? http://www.b.com/

127.0.0.1?????????? http://www.c.com/

SSO


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲视频一区二区 | 久久免费视频2 | 欧美成人香蕉在线观看 | 曰本毛片 | 奇米777四色影视 | 香蕉人人超人人超免费看视频 | 久久亚洲私人国产精品 | 热久久在线| 中文字幕亚洲高清综合 | 色婷婷久久综合中文网站 | 亚洲综合图片网 | 激情五月综合综合久久69 | 亚洲视频在线播放 | 九九视频精品全部免费播放 | 日本午夜大片a在线观看 | 国产亚洲欧美另类久久久 | 天天操天天干天天拍 | 色无极欧美 | 欧美在线播放一区二区 | 亚洲综合久久久久久中文字幕 | 91日本在线精品高清观看 | 亚洲精品tv久久久久 | 欧美黑大粗硬毛片视频 | 骚视频在线观看 | 亚洲视频999 | 99精品国产费观看视频 | 亚洲欧美日韩高清中文在线 | 久久午夜综合久久 | 成人亚洲国产精品久久 | 欧美日本一道免费一区三区 | 一级无遮挡理论片 | 亚洲 欧美 综合 | 九九精品激情在线视频 | 日韩伦理视频 | 久久网免费视频 | 久艹在线播放 | 黄色操视频 | 亚洲黄色小视频 | 国产在线精品香蕉麻豆 | 伊人久久网站 | 国产精品婷婷久久爽一下 |