誰都能看懂的單點登陸(SSO)實現方式(附源碼)

SSO的基本概念

SSO英文全稱Single Sign On(單點登陸)。SSO是在多個應用系統中,用戶只須要登陸一次就能夠訪問全部相互信任的應用系統。它包括能夠將此次主要的登陸映射到其餘應用中用於同一個用戶的登陸的機制。它是目前比較流行的企業業務整合的解決方案之一。(本段內容來自百度百科)html

今天這篇文章將介紹SSO的一種實現方式,代碼超簡單,僅用來驗證個人思路是否可行,具體細節請你們來完善!跨域

二級域名的單點登陸

什麼是二級域名呢?例如:服務器

  • site1.domain.com
  • site2.domain.com

對於二級域名的單點登陸,咱們能夠很是方便的經過共享cookie來實現,簡單的說,就是在設置Form票據的時候,將cookie的domain設置爲頂級域名便可,例如:cookie

HttpCookie cookie = new HttpCookie(FormsAuthCookieName, encryptedTicket);
cookie.Expires = rememberMe ? expirationDate : DateTime.MinValue;
cookie.HttpOnly = true;
cookie.Path = "/";
cookie.Domain = "domain.com";
context.Response.Cookies.Set(cookie);

這種方式不涉及跨域,當cookie的domain屬性設置爲頂級域名以後,全部的二級域名均可以訪問到身份驗證的cookie,在服務器端只要驗證了這個cookie就能夠實現身份的驗證。asp.net

可是,當跨域的時候,例如:dom

  • site1.com
  • site2.com

這個時候就不能共享cookie了,因此上面的解決方案就會失效。那麼,要實現跨域的單點登陸該如何作呢?請繼續往下看。this

跨域的單點登陸

關於跨域的SSO的設計思路,我畫了一個簡單的流程圖:url

image

首先,我將跨域的SSO分爲SSO-Server和SSO-Client兩個部分,SSO-Client能夠是多個的。.net

SSO-Server

SSO-Server主要負責用戶登陸、註銷、爲SSO-Client分配taken、驗證taken的工做。設計

登陸和註銷採用的是Form認證方式,不少地方都有詳細的介紹,我以前也寫過一篇文章,想了解的能夠去看看:asp.net Forms身份驗證詳解

SSO-Server分配Token

爲SSO-Client分配Token的部分,在SSO-Client請求SSO受信頁面的時候,檢查SSO-Server是否登陸,若是沒有登陸則跳轉到SSO-Server的登陸頁面,若是已登陸,則執行分配Token的代碼,在分配完成之後將TokenID做爲參數添加到returnUrl中,並跳轉到returnUrl,具體的分配代碼以下:

if (Domain.Security.SmartAuthenticate.LoginUser != null)
{
    //生成Token,並持久化Token
    Domain.SSO.Entity.SSOToken token = new Entity.SSOToken();
    
    token.User = new Entity.SSOUser();
    token.User.UserName = Domain.Security.SmartAuthenticate.LoginUser.UserName;
    token.LoginID = Session.SessionID;
    Domain.SSO.Entity.SSOToken.SSOTokenList.Add(token);

    //拼接返回的url,參數中帶Token
    string spliter = returnUrl.Contains('?') ? "&" : "?";
    returnUrl = returnUrl + spliter + "token=" + token.ID;
    Response.Redirect(returnUrl);
}

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

SSO-Server驗證Token

我是經過WebService來驗證Token的。

首先在SSO-Server定義一個Web Service:

[WebMethod]
public Entity.SSOToken ValidateToken(string tokenID)
{
    if (!KeepToken(tokenID))
        return null;

    var token = Domain.SSO.Entity.SSOToken.SSOTokenList.Find(m => m.ID == tokenID);
    return token;
}

[WebMethod]
public bool KeepToken(string tokenID)
{
    var token = Domain.SSO.Entity.SSOToken.SSOTokenList.Find(m => m.ID == tokenID);
    if (token == null)
        return false;
    if (token.IsTimeOut())
        return false;

    token.AuthTime = DateTime.Now;
    return true;
}

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

SSO-Client經過調用Validate驗證Token,並獲得當前的登陸用戶信息。接下來看看SSO-Client的實現。

SSO-Client

SSO-Client做爲受信系統來存在的,它本身沒有認證系統,只能經過SSO-Server來完成用戶身份認證的工做。

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

驗證成功之後將會返回SSOToken的實例,裏面包含已登陸的用戶信息。具體代碼以下:

if (!string.IsNullOrEmpty(tokenID))
{
    AuthTokenService.AuthTokenServiceSoapClient client = new AuthTokenService.AuthTokenServiceSoapClient();
    var token = client.ValidateToken(tokenID);
    if (token != null)
    {
        this.lblMessage.Text = "登陸成功,登陸用戶:"
            + token.User.UserName
            + "<a href='http://sso-server.com/logout.aspx?returnUrl="
            + Server.UrlEncode("http://sso-client.com")
            + "'>退出</a>";
    }
    else
    {
        Response.Redirect("http://sso-server.com/sso.aspx?returnUrl=" +
            Server.UrlEncode("http://sso-client.com/default.aspx"));
    }
}
else
{
    Response.Redirect("http://sso-server.com/sso.aspx?returnUrl=" +
        Server.UrlEncode("http://sso-client.com/default.aspx"));
}

源代碼

文章中已經介紹了個人具體思路和一些實現,若是你仍然感興趣,能夠下載個人代碼>>Demo.SSO

源代碼的部署:

1. 在IIS中建立兩個站點,分別綁定到SSO-Server和SSO-Client,它們綁定的域名分別是sso-server.com和sso-client.com

2. 在hosts文件中添加兩行映射,將sso-server.com和sso-client.com映射到127.0.0.1,確保能夠訪問

3.訪問sso-client.com,這個時候頁面將跳轉到sso-server.com的登陸頁面,用戶名、密碼隨便輸入,而後點擊登陸便可

 

我很認真的完成了這個方案,也感謝你很認真的看完!歡迎拍磚!

相關文章
相關標籤/搜索