我已经这样做了。基本思想是你的主要认证形式是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中设置并指向调试器。
请告诉我们您的代码 –