.Net單點登錄詳解 (SSO)
來源:程序員人生 發布時間:2014-12-15 08:48:36 閱讀次數:3058次
最近做GXP(高校平臺)的項目,由于里邊有好多個子系統,例如有考試系統,評教系統,基礎系統,新生入學系統,權限系統,如果每一個系統都有自己的獨立的登錄的界面,那末就會有能訪問這5個系統的人就要記住5套用戶名,密碼。哇,好累啊,5套!在這個背景下提出了單點登錄(SSO)。
先來講說甚么是單點登錄(SSO),單點登錄(Single Sign On),簡稱為 SSO,是目前比較流行的企業業務整合的解決方案之1。SSO的定義是在多個利用系統中,用戶只需要登錄1次就能夠訪問所有相互信任的利用系統。單點登錄簡單來講,就1處登錄,可以到處訪問。
SSO的解決方案很多,比如收費的有UTrust、惠普靈動等,開源的有CAS、Smart SSO等,其中利用最為廣泛的是CAS。但是因本人能力有限,沒有做出cas在.net下的利用。所有這篇文章來介紹1下摹擬cas情勢做的1個登錄,請大家多多批評指正。
讓我們來看看cas的工作原理!


當用戶在地址欄中輸入我們想訪問的地址后,例如輸入基礎系統的url地址,基礎系統的服務器會檢測有無發過來票據(ST),如果沒有,那末會跳轉到認證中心服務器端,當發送到認證中心服務器端后,認證中心服務器端會檢查有無有無發過來CooKie,如果沒有,那末就會那末就會出現登錄界面,讓用戶輸入用戶名,密碼,然后回去數據庫中進行驗證,如果用戶輸入的正確,那末會生成1個票據(ST)和保存用戶名的Cookie,票據(ST)中包括:要訪問系統的URL,和進入該系統的唯1憑證。返回給閱讀器,閱讀器接受后,會保存Cookie,然后通過ST中的URL轉到要訪問系統的服務器,進入該服務器后,仍然后檢測有無ST,現在又ST,那末他會拿著這個ST中的唯1憑證去認證中心服務器進行比對,看看該唯1憑證是否是認證中心服務器端生成的,如果是的話啊,那末就返回用戶信息!并展現頁面給用戶!。
說了這么多,給大家看1個例子。先看1下這個例子的結構!

這個例子中有3個項目,分別為:MasterSite,site1,site2.MasterSite 摹擬認證中心服務器,site1摹擬其中的1個利用,site2摹擬另外一個利用!
讓我們看1下主要的代碼!
驗證服務器真個登錄頁的后臺代碼。首先檢查發過來的要求中包括的信息都有甚么,
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;
public partial class _Default : System.Web.UI.Page
{
/// <summary>
///
服務器真個登錄頁面的類
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SSORequest ssoRequest = new SSORequest();
#region 驗證 Post 過來的參數
//--------------------------------
// 要求注銷
if (!string.IsNullOrEmpty(Request["Logout"]))
{
Authentication.Logout();
return;
}
//--------------------------------
// 各獨立站點標識
if (string.IsNullOrEmpty(Request["IASID"]))
{
return;
}
else
{
ssoRequest.IASID = Request["IASID"];
}
//--------------------------------
// 時間戳
if (string.IsNullOrEmpty(Request["TimeStamp"]))
{
return;
}
else
{
ssoRequest.TimeStamp = Request["TimeStamp"];
}
//--------------------------------
// 各獨立站點的訪問地址
if (string.IsNullOrEmpty(Request["AppUrl"]))
{
return;
}
else
{
ssoRequest.AppUrl = Request["AppUrl"];
}
//--------------------------------
// 各獨立站點的 Token
if (string.IsNullOrEmpty(Request["Authenticator"]))
{
return;
}
else
{
ssoRequest.Authenticator = Request["Authenticator"];
}
ViewState["SSORequest"] = ssoRequest;
#endregion
//驗證從分站發過來的Token
if (Authentication.ValidateAppToken(ssoRequest))
{
string userAccount = null;
// 驗證用戶之前是不是登錄過
//驗證 EAC 認證中心的 Cookie,驗證通過時獲得用戶登錄賬號
if (Authentication.ValidateEACCookie(out userAccount))
{
ssoRequest.UserAccount = userAccount;
//創建認證中心發往各分站的 Token
if (Authentication.CreateEACToken(ssoRequest))
{
Post(ssoRequest);
}
}
else
{
return;
}
}
else
{
return;
}
}
}
//post要求
void Post(SSORequest ssoRequest)
{
PostService ps = new PostService();
ps.Url = ssoRequest.AppUrl;
ps.Add("UserAccount", ssoRequest.UserAccount);
ps.Add("IASID", ssoRequest.IASID);
ps.Add("TimeStamp", ssoRequest.TimeStamp);
ps.Add("AppUrl", ssoRequest.AppUrl);
ps.Add("Authenticator", ssoRequest.Authenticator);
ps.Post();
}
/// <summary>
/// 驗證登錄賬號和密碼是不是正確
/// </summary>
/// <param name="userName">登錄賬號</param>
/// <param name="userPwd">登錄密碼</param>
/// <returns></returns>
private bool ValidateUserInfo(string userName, string userPwd)
{
//從
數據庫中讀取,驗證登錄賬號和密碼
//略...
return true;
}
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
if (string.IsNullOrEmpty(Login1.UserName) || string.IsNullOrEmpty(Login1.Password))
{
Page.RegisterClientScriptBlock("Add", "<script lanuage="javascript">alert('用戶名密碼不能為空!');</script>");
return;
}
else if (ValidateUserInfo(Login1.UserName, Login1.Password) == false)
{
Page.RegisterClientScriptBlock("Add", "<script lanuage="javascript">alert('用戶名密碼毛病!');</script>");
return;
}
else
{
//保存當前用戶的用戶名
Session["CurrUserName"] = Login1.UserName;
//設置過期時間 單位為分鐘
Session.Timeout = 120;
SSORequest ssoRequest = ViewState["SSORequest"] as SSORequest;
// 如果不是從各分站 Post 過來的要求,則默許登錄主站
if (ssoRequest == null)
{
FormsAuthentication.SetAuthCookie(Login1.UserName, false);
ssoRequest = new SSORequest();
//主站標識ID
ssoRequest.IASID = "00";
ssoRequest.AppUrl = "SiteList.aspx";
ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
ssoRequest.Authenticator = string.Empty;
Response.Redirect("SiteList.aspx");
}
ssoRequest.UserAccount = Login1.UserName;
//創建Token
if (Authentication.CreateEACToken(ssoRequest))
{
string expireTime = DateTime.Now.AddHours(3).ToString("yyyy-MM-dd HH:mm");
Authentication.CreatEACCookie(ssoRequest.UserAccount, ssoRequest.TimeStamp, expireTime);
Post(ssoRequest);
}
}
}
}
</pre><p></p><p> <span style="font-size:18px"> 該類主要是將要發送的要求封裝起來成為1個類進行發送!</span></p><p><span style="font-size:18px"></span></p><pre name="code" class="html">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;
/// <summary>
/// SSORequest 該類主要是設置要求包,要求包中都包括哪些信息!
/// 繼承MarshalByRefObject ,主要解決跨域訪問的問題!
/// </summary>
[Serializable]
public class SSORequest : MarshalByRefObject
{
public string IASID; //各獨立站點標識ID
public string TimeStamp; //時間戳
public string AppUrl; //各獨立站點的訪問地址
public string Authenticator; //各獨立站點的 Token
public string UserAccount; //賬號
public string Password; //密碼
public string IPAddress; //IP地址
//為ssresponse對象做準備
public string ErrorDescription = "認證失敗"; //用戶認證通過,認證失敗,包數據格式不正確,數據校驗不正確
public int Result = ⑴;
public SSORequest()
{
}
/// <summary>
/// 獲得當前頁面上的SSORequest對象
/// </summary>
/// <param name="CurrentPage"></param>
/// <returns></returns>
public static SSORequest GetRequest(Page CurrentPage)
{
SSORequest request = new SSORequest();
request.IPAddress = CurrentPage.Request.UserHostAddress;
request.IASID = CurrentPage.Request["IASID"].ToString();// Request本身會Decode
request.UserAccount = CurrentPage.Request["UserAccount"].ToString();//this.Text
request.Password = CurrentPage.Request["Password"].ToString();
request.AppUrl = CurrentPage.Request["AppUrl"].ToString();
request.Authenticator = CurrentPage.Request["Authenticator"].ToString();
request.TimeStamp = CurrentPage.Request["TimeStamp"].ToString();
return request;
}
}
該類的主要作用是發送要求,或將遭到的要求進行處理,發后回送要求信息!
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
/// <summary>
/// 該類的主要作用是發送要求,
/// 或將遭到的要求進行處理,發后回送要求信息!
/// </summary>
public class PostService
{
private System.Collections.Specialized.NameValueCollection Inputs = new System.Collections.Specialized.NameValueCollection();
public string Url = "";
public string Method = "post";
public string FormName = "form1";
/// <summary>
/// 添加需要提交的名和值
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public void Add(string name, string value)
{
Inputs.Add(name, value);
}
/// <summary>
/// 以輸出Html方式POST
/// </summary>
public void Post()
{
System.Web.HttpContext.Current.Response.Clear();
string html = string.Empty;
html += ("<html><head>");
html += (string.Format("</head><body onload="document.{0}.submit()">", FormName));
html += (string.Format("<form name="{0}" method="{1}" action="{2}" >", FormName, Method, Url));
try
{
for (int i = 0; i < Inputs.Keys.Count; i++)
{
html += (string.Format("<input name="{0}" type="hidden" value="{1}">", Inputs.Keys[i], Inputs[Inputs.Keys[i]]));
}
html += ("</form>");
html += ("</body></html>");
System.Web.HttpContext.Current.Response.Write(html);
System.Web.HttpContext.Current.Response.End();
}
catch (Exception e)
{
}
}
}</span>
安全驗證類,主要對發送過來的票據進行驗證!
<span style="font-size:18px;">using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Collections.Generic;
using System.Text;
/// <summary>
/// 安全驗證類
/// </summary>
public class Authentication
{
static readonly string cookieName = "EACToken";
static readonly string hashSplitter = "|";
public Authentication()
{
}
public static string GetAppKey(int appID)
{
//string cmdText = @"select * from ";
return string.Empty;
}
public static string GetAppKey()
{
return "22362E7A9285DD53A0BBC2932F9733C505DC04EDBFE00D70";
}
public static string GetAppIV()
{
return "1E7FA9231E7FA923";
}
/// <summary>
/// 獲得加密服務
/// </summary>
/// <returns></returns>
static CryptoService GetCryptoService()
{
string key = GetAppKey();
string IV = GetAppIV();
CryptoService cs = new CryptoService(key, IV);
return cs;
}
/// <summary>
/// 創建各分站發往認證中心的 Token
/// </summary>
/// <param name="ssoRequest"></param>
/// <returns></returns>
public static bool CreateAppToken(SSORequest ssoRequest)
{
string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
CryptoService cs = GetCryptoService();
byte[] encrypted;
if (cs.Encrypt(bToEncrypt, out encrypted))
{
ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
return true;
}
else
{
return false;
}
}
/// <summary>
/// 驗證從各分站發送過來的 Token
/// </summary>
/// <param name="ssoRequest"></param>
/// <returns></returns>
public static bool ValidateAppToken(SSORequest ssoRequest)
{
string Authenticator = ssoRequest.Authenticator;
string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
CryptoService cs = GetCryptoService();
byte[] encrypted;
if (cs.Encrypt(bToEncrypt, out encrypted))
{
return Authenticator == CryptoHelper.ToBase64String(encrypted);
}
else
{
return false;
}
}
/// <summary>
/// 創建認證中心發往各分站的 Token
/// </summary>
/// <param name="ssoRequest"></param>
/// <returns></returns>
public static bool CreateEACToken(SSORequest ssoRequest)
{
string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
CryptoService cs = GetCryptoService();
byte[] encrypted;
if (cs.Encrypt(bToEncrypt, out encrypted))
{
ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
return true;
}
else
{
return false;
}
}
/// <summary>
/// 驗證從認證中心發送過來的 Token
/// </summary>
/// <param name="ssoRequest"></param>
/// <returns></returns>
public static bool ValidateEACToken(SSORequest ssoRequest)
{
string Authenticator = ssoRequest.Authenticator;
string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
string EncryCurrentAuthenticator = string.Empty;
CryptoService cs = GetCryptoService();
byte[] encrypted;
if (cs.Encrypt(bToEncrypt, out encrypted))
{
EncryCurrentAuthenticator = CryptoHelper.ToBase64String(encrypted);
return Authenticator == EncryCurrentAuthenticator;
}
else
{
return false;
}
}
/// <summary>
/// 創建 EAC 認證中心的 Cookie
/// </summary>
/// <param name="userAccount"></param>
/// <param name="timeStamp"></param>
/// <param name="expireTime"></param>
/// <param name="cookieValue"></param>
/// <returns></returns>
public static bool CreatEACCookie(string userAccount, string timeStamp, string expireTime)
{
string plainText = "UserAccount=" + userAccount + ";TimeStamp=" + timeStamp + ";ExpireTime=" + expireTime;
plainText += hashSplitter + CryptoHelper.ComputeHashString(plainText);
CryptoService cs = GetCryptoService();
byte[] encrypted;
if (cs.Encrypt(CryptoHelper.ConvertStringToByteArray(plainText), out encrypted))
{
string cookieValue = CryptoHelper.ToBase64String(encrypted);
SetCookie(cookieValue);
return true;
}
else
{
return false;
}
}
/// <summary>
/// 驗證 EAC 認證中心的 Cookie,驗證通過時獲得用戶登錄賬號
/// </summary>
/// <param name="userAccount">輸出用戶登錄賬號</param>
/// <returns></returns>
public static bool ValidateEACCookie(out string userAccount)
{
userAccount = string.Empty;
try
{
string cookieValue = GetCookie().Value;
byte[] toDecrypt = CryptoHelper.FromBase64String(cookieValue);
CryptoService cs = GetCryptoService();
string decrypted = string.Empty;
if (cs.Decrypt(toDecrypt, out decrypted))
{
string[] arrTemp = decrypted.Split(Convert.ToChar(hashSplitter));
string plainText = arrTemp[0];
string hashedText = arrTemp[1];
userAccount = plainText.Split(Convert.ToChar(";"))[0].Split(Convert.ToChar("="))[1];
return hashedText.Replace("
主站蜘蛛池模板:
美国xxxx69|
亚洲精品无码专区在线播放
|
亚洲综合福利
|
免费大片在线观看www
|
福利在线免费
|
一区二区精品
|
日韩精品一区二区三区中文字幕
|
波多野结衣在线观看一区二区三区
|
国产1区二区
|
视频一区中文字幕
|
日韩欧美一区二区在线观看
|
日韩久久久精品中文字幕
|
亚洲人成亚洲精品
|
伊人高清视频
|
一级毛片在线免费视频
|
久久久久毛片成人精品
|
18网站在线观看
|
中文字幕视频在线免费观看
|
亚洲人成在线播放网站
|
亚洲最大免费视频网
|
亚洲一区二区三区四区视频
|
午夜又黄又爽
|
欧美一级特毛片
|
亚洲美女色视频
|
国产啪精品视频网免费
|
国产一区2区
|
国产一级做a爱片久久毛片a
|
99精品欧美一区二区三区
|
人成午夜视频
|
欧美日韩一区二区三区色综合
|
男女激情视频
|
成人在线视频国产
|
成人午夜视频一区二区国语
|
老司机av|
www.色午夜|
羞羞网站免费观看
|
国产一区二区三区在线观看精品
|
色猫av
|
国产免费叼嘿网站免费
|
上海一级毛片
|
精品久久中文字幕有码
|