Active Directory使用表单身份验证和Windows身份验证

时间:2017-04-04 11:46:25

标签: c# asp.net authentication active-directory adfs

我有一个ASP.Net应用程序。要求是使用ADFS实现表单身份验证。 如果用户正在域内(与Active Directoris相同的域)访问WebSite,则应执行表单身份验证。 即,使用用户的Windows登录电子邮件ID,我们应该检查用户是否存在于Active Directory中。如果用户存在,则用户可以访问该网站。 如果未根据他/她的电子邮件ID找到用户,则向用户询问他/她的用户名和密码,并选择应在其上搜索用户的两个活动目录之一。 (PN:有两个活动目录。一个默认用于在域中使用。)

如果用户从域外访问网站,则始终向用户询问他/她的用户名和密码,并选择用户所属的两个活动目录中的一个。

因此,有一个URL可以在域中访问网站,另一个可以从域外访问。

我需要帮助来完成这项任务。 该项目位于Dot.Net,使用ASP.Net和C#上的Framework 3.5。

高度赞赏代码解决方案的帮助。

2 个答案:

答案 0 :(得分:1)

我做到了这一点。基本思想是您的主要身份验证形式是表单。但是,您使默认登录页面使用Windows身份验证。如果Windows身份验证成功,则创建Forms票证并继续。如果没有,则显示登录页面。

唯一需要注意的是,由于Windows身份验证始终向浏览器发送401响应(对Windows凭据提出质疑),因此非域用户将始终获得一个凭据弹出窗口,他们必须单击“取消”。 / p>

我在我的项目中使用了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中设置它并将调试器指向该位置。

答案 1 :(得分:0)

OOTB解决方案可能适合您。

同时使用ADFS WAP并设置裂脑DNS。

内部用户(在域内)获取ADFS框的DNS。默认为Windows身份验证。 (IWA)

外部用户(域外)获取ADFS WAP框的DNS。默认值为FBA。