混和認證模式(Window/Form)偷懶版

這個議題主要是我利用PC/IPAD/Android手機測試我開發的ASP.NET系統的時候,延伸出來的一個研究項目。主要因為該系統是採用Windows驗證的方式進行權限控管,在上述的三個裝置連結系統的結果如下:
  • PC - 原本就在Domain內的PC,並且為主要測試裝置所以完全沒問題。
  • iPad - 連結網頁時,瀏覽器會彈出驗證視窗,要求輸入Domain帳密,正確後就可正常使用。
  • Android Mobile - 連結網頁直接空白,也沒談出驗證視窗,直接無法使用系統。
上述Andorid裝置也能夠使用我開發的ASP.NET系統,因此必須讓Andorid手機可以允許以Form驗證的方式來進行AD認證,不過在測試過程中遇到幾個問題:
  • 如果將IIS改成匿名存取的方式或Form驗證的方式,則原本PC不用輸入帳密的動作必須改成每次都入都必須輸入帳密,這破壞了原本最多使用者的登入方式,造成改善過程反而更多人不方便,所以不採用。
  • 原本IIS採用Windows驗證方式,於Android Mobile直接空白的情況下連驗證機會都沒有,造成無法使用因此也不適合。
最理想的方式當然是讓PC/iPad採用整合認證,但是仍然給Andoird手機採用匿名存取之後再導到Form驗證,如圖第三列的方式。


實現方式:
  • 將整個WebSite以匿名存取方式建置在IIS,但系統設計上沒有身分驗證需導到Login Page提供以程式方式進行Domain身分驗證。
  • 在WebSite中設計一個NTLM.ashx,並且特別於IIS上設定為此ashx為Window驗證模式,在此ashx內取得Windows認證的帳號,如果有取得帳號時,將該帳號對應到此系統登入身分。
public class NTLM : IHttpHandler, IRequiresSessionState {
    public void ProcessRequest(HttpContext context) {
        string DomainUser=null;
        if (System.Web.HttpContext.Current != null) {
            // Get Win Auth Account
            DomainUser = System.Web.HttpContext.Current.Request.ServerVariables["AUTH_USER"];
        }
        // return json data for ajax
        // success:{'DomainUser':DomainUser}
        // fail:{}
        context.Response.ContentType = "application/json";
        if (DomainUser != null) {            
            context.Response.Write("{'DomainUser':'"+DomainUser+"'}");
            // save to session
            context.Session["LOGINID"] = DomainUser.Split(new string[] { "\\" })[1];            
        }
        else {
            context.Response.Write("{}");
        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }
}
  • 登入系統時,系統以ajax方式讀取NTLM.asxh確認是否有取得Window認證帳號,此時三種裝置的ajax狀態如下:
    • PC: 直接取得DomainUser資料,且後端Session已經儲存該資訊。
    • iPAD:彈出認證視窗要求輸入帳密,輸入正確則取得DomainUser資料,否則ajax將發生error。
    • Andorid Mobile:ajax發生error訊息,將網頁導向自行設計的Login Page要求以Form方式輸入帳密,在後端依據輸入內容前往AD Server進行認證。
$.getJSON('Portal/NTLM.ashx', function (data) {
    if (data.LogonId != null) {
        redirectByDevice();
    }
    else {
        redirectToLogin();
    }
})
.error(function (e) {
    redirectToLogin();
});
經過上述步驟,就可以達成偷懶版混和驗證。


沒有留言:

橫式廣告