【黑暗執行緒】奇技淫巧 - ASP.NET 同時支援 Form 及 Windows 驗證

2022/6/1

跟同事討論到 ASP.NET/IIS 有沒可能同時支援 Windows 驗證跟 Form 驗證?依我的理解,每個 Web Application 只能二者擇一,要嘛走 Windows 驗證、要嘛用 Form 驗證。討論到後來,我對自己發出靈魂拷問:ASP.NET 應用程式真的沒辦法做到使用 Form 驗證又能用 Windows 整合式驗證嗎?

過去我能想到的方法是開兩個 Web Appliation 分別跑 Form 驗證及 Windows 驗證,再自己寫 SSO 機制串接;或是 Form 接入 AD 帳號密碼再走 LDAP 或其他方式驗證帳號密碼(缺點是程式端會拿到 AD 帳密,需面對帳號密碼可能被儲存或外流的質疑,我個人偏好「閃開! 讓專業的瀏覽器跟 IIS 來處理」)。沒法像下面這樣,在原本使用 Form 驗證的 Web Applicaion 加一個鈕讓使用者改用 Windows 驗證登入:

這... 所以,現在大家知道答案了,是的! 這是有可能做到的。

上面的範例是我參考網路文章實做出來的,整理重點如下:

  1. 使用 Form 或 Windows 驗證,由 web.config 的 system.web/authentiation 與 application.config system.webServer/security/authentication 控制 (延伸閱讀:【答客問】IIS 與 web.config 的 Windows 驗證設定),預設我們無法切換特定網址的 Windows 驗證,像是全站用 Form 驗證,只有 LoginAD.aspx 用 Windows 驗證:
    
    
    將導致 503.19 錯誤:

    但我們調整 IIS 設定:

    或修改 applicationhost.config 可解除此一限制:(衍生風險為無管理者權限者可以修改 web.config 避開 Windows 驗證,但前題要拿到更改網站檔案的權限)

    (用 Visual Studio/IISExpress 測試的話,要改 .vs\ProjName\config\applicationhost.conf)
  2. 由於全站開 Form 驗證,預設連到 LoginAD.aspx 時也會被導向 Login.aspx,要靠 Global.asax 加入 Application_EndRequest() 發現 LoginAD.aspx 被導走時改傳 401:
    
    
  3. LoginAD.aspx 的任務是取得 Windows 登入身分將其轉成 FormAuthentiation Cookie:
    
    

總之透過以上精巧安排,我們就能在 Form 驗證加個按鈕,按下去改用 AD 帳號登入,感覺挺酷的,可適用除了 AD 帳號還有自訂帳號的應用場合。

範例為求簡便是用 WebForm 實作,但搬到 ASP.NET MVC 使用也是 OK 的。老樣子,範例程式已放上 Github,有需要的朋友請自取參考。

【參考資料】

本文分享自 暗黑執行緒