我已經這樣做了。基本思想是你的主要認證形式是Forms。但是,您使默認登錄頁面使用Windows身份驗證。如果Windows身份驗證成功,則創建「表單」工單並繼續。如果不是,則顯示登錄頁面。
唯一需要注意的是,由於Windows身份驗證始終向瀏覽器發送401響應(對Windows憑據進行挑戰),因此非域用戶將始終獲得憑據彈出窗口,他們必須單擊「取消」。
我在我的項目中使用了MVC。我的Windows登錄頁面是/Login/Windows
,我的手動登錄頁面是/Login
。
這裏是我的web.config的相關領域:
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Login/Windows" defaultUrl="~/" name=".MVCFORMSAUTH" protection="All" timeout="2880" slidingExpiration="true" />
</authentication>
<system.web>
<location path="Login">
<system.web>
<authorization>
<allow users="?" />
<allow users="*" />
</authorization>
</system.web>
</location>
<location path="Login/Windows">
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
</security>
<httpErrors errorMode="Detailed" />
</system.webServer>
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
這裏是我的LoginController:
[RoutePrefix("Login")]
public class LoginController : Controller {
[Route("")]
public ActionResult Login() {
//Clear previous credentials
if (Request.IsAuthenticated) {
FormsAuthentication.SignOut();
Session.RemoveAll();
Session.Clear();
Session.Abandon();
}
return View();
}
[Route("")]
[HttpPost]
public ActionResult TryLogin(string username, string password) {
//Verify username and password however you need to
FormsAuthentication.RedirectFromLoginPage(username, true);
return null;
}
[Route("Windows")]
public ActionResult Windows() {
var principal = Thread.CurrentPrincipal;
if (principal == null || !principal.Identity.IsAuthenticated) {
//Windows authentication failed
return Redirect(Url.Action("Login", "Login") + "?" + Request.QueryString);
}
//User is validated, so let's set the authentication cookie
FormsAuthentication.RedirectFromLoginPage(principal.Identity.Name, true);
return null;
}
}
你登錄查看將只是一個正常的用戶名/密碼形式,做了POST登錄。
在這一點上,你有一個/Login
頁面,人們可以手動去登錄。您還有一個/Login/Windows
頁面,該頁面是人們自動重定向到的默認登錄頁面。但是,如果Windows登錄失敗,它將顯示一個通用的401錯誤頁面。
使這種無縫的關鍵是使用您的登錄視圖作爲您的自定義401錯誤頁面。我通過使用ViewRenderer class written by Rick Strahl劫持Application_EndRequest
中的響應內容來做到這一點。
的Global.asax.cs:
protected void Application_EndRequest(object sender, EventArgs e) {
if (Response.StatusCode != 401 || !Request.Url.ToString().Contains("Login/Windows")) return;
//If Windows authentication failed, inject the forms login page as the response content
Response.ClearContent();
var r = new ViewRenderer();
Response.Write(r.RenderViewToString("~/Views/Login/Login.cshtml"));
}
另一個需要注意的,我發現的是,這並不在IIS Express中(雖然它是一個或兩個版本,因爲我上次嘗試)。我有它在IIS中設置並指向調試器。
請告訴我們您的代碼 –