[開發環境] NetCore 站台套用 Single Sign-On 登入機制

單一登入(Single Sign-On,簡稱SSO)是一種身份驗證技術,它允許使用者在訪問多個應用程式或系統時只需通過一次身份驗證就能夠登入,也就是說使用者只需要輸入一次他們的帳號和密碼,就能夠輕鬆地存取各種應用程式,而無需反覆輸入驗證資訊。

本文的目的就是在於記錄如何實現在 .Net Core 站台中,直接驗證使用者當前登入的 Windows 電腦帳號的相關設定及程式碼,相關說明如下
  • 若是託管在 IIS 中的,記得啟用 IIS 角色中的 Winodws 驗證

  • 若使用的網址是 IP 或 Domain ,而不是 內部伺服器名稱(Server PC Name) 的話,會因為非近端網路,而跳出底下瀏覽器預設的登入畫面,解決辦法是要在 IE 加信任的網站 ,也可以使用註冊機碼來解決,但此方法僅適用在 Chorme & Edge,並且在無痕模式下並不適用。

  • 新增 Windows 身份驗證服務 程式碼 (IIS Only)。
    // Windows 認證無法支援 Kestrel,僅在 IIS 上面可運作,並且要先將 windows 認證一併開啟
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    
  • 透過 Microsoft.AspNetCore.Authentication.Negotiate 套件,可以讓 Kestrel 環境也能支援 Winodws 認證。
    // 此套件有一個問題是 IIS 要是沒有啟動 Windows 認證會直接拋出 Exception 導致站台無法啟用
    // 無法達到動態控制站台是否支援 Windows 認證的需求,所以才不使用
    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
    
  • 要套用的 API 要指定驗證類型。
    [ApiController]
    [Route("api/[controller]")]
    public class SingleSignOnController : ControllerBase
    {
        [Authorize(AuthenticationSchemes = IISDefaults.AuthenticationScheme)]
        [HttpGet("eip-token")]
        public async Task GetEipTokenAsync()
        {
           // TODO: 
        }
    }
  • IIS 使用上小問題,因為站台上面同時使用 JWT Tokne 和 Windows 驗證,因此當 JWT Token 過期時,會導致 IIS 自動改用 Windows 驗證,而導致原本使用 JWT Token 的 API 也跳出 Windows 登入畫面,解決辦法,當 JWT Token 過期時,前端移除 Http Header 夾帶的 Authorization Bearer,此時就會回到 JWT 未登入的驗證機制直接拋回 401 錯誤了,例如底下的判斷方式。
    /** TypeScript 前端判斷是否登入 */
    get IsSignin(): boolean {
      if (!this.UserInfo) return false;
      if (!this.UserInfo.token) return false;
    
      try {
        const token = this.UserInfo.token;
        const tokeInfo = JSON.parse(atob(token.split('.')[1]));
        const exp = new Date(tokeInfo.exp * 1000);
        return exp > new Date();
      }
      catch {
        return false;
      }
    }

參考網站

留言