萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> ASP.NET 程式設計

.NET 單一登入 (SSO) 實作架構與程式碼完整解析

系統架構

  • Service (身分驗證中心):管理使用者帳號、登入/登出、Session 狀態。
  • Shop / Office (應用系統):業務系統,委派驗證給 Service。

流程圖解

  1. 使用者存取 Shop/Office 任一頁面 (Any.aspx)。
  2. 應用系統檢查本地 Session Pass。若無效 → 導向 Service/Validate.aspx 攜帶 WebSite (回呼網址) 與 Security (單次驗證碼)。
  3. Service 驗證使用者狀態:
    • 已登入 → 導向 Shop/Office 的 Synchronous.aspx 同步 Session,並帶回 Security 的雜湊值。
    • 未登入 → 導向 Login.aspx 登入,成功後同步回應用系統。
  4. 應用系統驗證回傳的 Security 雜湊值,通過則建立本地 Session,導向原請求頁面。

關鍵程式碼片段

Shop Global.asax - Session 初始化

protected void Session_Start(object sender, EventArgs e)
{
    Session["UserID"] = 0;
    Session["Pass"] = false;
    Session["Security"] = "";
    Session["ReturnUrl"] = "";
}

Shop 基底頁面 - 驗證邏輯


public class BasePage : Page
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        if (!ValidateSession())
            RedirectToAuthCenter();
    }

    private bool ValidateSession()
    {
        return (bool)Session["Pass"];
    }

    private void RedirectToAuthCenter()
    {
        // 產生單次驗證碼
        string security = GenerateSecurityToken();
        Session["Security"] = security;
        Session["ReturnUrl"] = Request.RawUrl;

        string authUrl = $"{AuthCenterUrl}/Validate.aspx?WebSite={Server.UrlEncode(AppUrl)}&Security={security}";
        Response.Redirect(authUrl);
    }

    private string GenerateSecurityToken()
    {
        byte[] bytes = new byte[32];
        using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create())
            rng.GetBytes(bytes);
        return Convert.ToBase64String(bytes);
    }
}

Service Validate.aspx - 驗證與同步


protected void Page_Load(object sender, EventArgs e)
{
    string webSite = Request.QueryString["WebSite"];
    string security = Request.QueryString["Security"];
    Session["WebSite"] = webSite;
    Session["Security"] = security; // 記錄原始驗證碼

    if ((bool)Session["Pass"]) // 已登入
    {
        // 回傳雜湊後的 Security 給應用系統
        string hashed = HashSecurity(security);
        Response.Redirect($"{webSite}/Synchronous.aspx?Security={Server.UrlEncode(hashed)}");
    }
    else
    {
        Response.Redirect("Login.aspx");
    }
}

private string HashSecurity(string input)
{
    using (var sha = SHA512.Create())
    {
        byte[] hash = sha.ComputeHash(Encoding.Unicode.GetBytes(input));
        return Convert.ToBase64String(hash);
    }
}

Shop Synchronous.aspx - 同步驗證


protected void Page_Load(object sender, EventArgs e)
{
    string returnedHash = Request.QueryString["Security"];
    string original = (string)Session["Security"];
    string expectedHash = HashSecurity(original);

    if (returnedHash == expectedHash)
    {
        Session["Pass"] = true;
        Session["UserID"] = 123; // 實際應從 Service 取得 UserID
        string returnUrl = (string)Session["ReturnUrl"] ?? "Default.aspx";
        Response.Redirect(returnUrl);
    }
    else
    {
        Response.Write("驗證失敗,可能遭竄改");
    }
}

安全性考量

  • Security Token:單次隨機數,防重放攻擊。
  • SHA512 雜湊:確保回傳資料未被竄改。
  • HTTPS:所有傳輸必須加密。
  • 同網域/跨網域 Cookie:若共用父網域,可直接共享 FormsAuthentication Cookie,簡化架構。

現代替代方案

  • OAuth 2.0 / OpenID Connect:IdentityServer4、Keycloak、Auth0、Azure AD。
  • SAML 2.0:企業級聯盟身分識別。
  • JWT (JSON Web Token):無狀態、可攜帶 Claims、微服務友善。

結語

本文展示傳統 ASP.NET WebForms 時代的 SSO 手工實作邏輯,理解其原理有助於掌握現代標準協定的運作基礎。新專案強烈建議採用成熟的 Identity Provider 框架。

copyright © 萬盛學電腦網 all rights reserved