使用表单身份验证和Windows身份验证的Active Directory [英] Active Directory Using Form Auth and Windows Auth

查看:287
本文介绍了使用表单身份验证和Windows身份验证的Active Directory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如果用户正在从域外部访问网站,则总是询问用户其用户名和密码,并选择用户所属的两个活动目录之一.

因此,有一个URL可以从域中访问with,而有一个URL可以从域外部访问.

我需要帮助才能完成此任务. 该项目位于Dot.Net中,在ASP.Net和C#上使用Framework 3.5.

高度赞赏有关代码解决方案的帮助.

解决方案

我已经做到了.基本思想是,身份验证的主要形式是表格.但是,您可以使默认登录页面使用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页面,人们可以手动进入该页面.您还拥有一个/Login/Windows页面,这是用户自动重定向到的默认登录页面.但是,如果Windows登录失败,它将显示一个通用的401错误页面.

实现无缝连接的关键是使用登录"视图作为自定义401错误页面.我通过使用

我发现的另一个警告是,这在IIS Express中不起作用(尽管自上次尝试以来已经是一两个版本).我在IIS中安装了它,然后将调试器指向了它.

I have an ASP.Net Application. The requirement is to implement Form Authentication using ADFS. If the user is accessing the WebSite from within the Domain(the same Domain as the Active Directoris), then the Form Authentication should be performed. i.e. Using the User's Windows logged in email Id, we should check if the user exists in the Active Directory or not. If the user exists, then the Website is made accessible to the user. If the user is not found on the basis of his/her email id, then the user is asked his/her UserName and Password, and to select one of the Two Active Directories on which the user should be searched. (PN: There are two Active Directories. One Default for using with-in the Domain.)

If the User is accessing the Website from outside the Domain, then the user is always asked his/her UserName and Password, and to select one of the two Active Directories to which the User Belongs.

So, there is one URL to access the Website from with in the Domain, and one to access from Outside the Domain.

And I need help to accomplish this task. The project is in Dot.Net, using Framework 3.5 on ASP.Net and C#.

Help with code solution highly appreciated.

解决方案

I have done this. The basic idea is that your main form of authentication is Forms. However you make your default login page use Windows authentication. If the Windows authentication succeeds, then you create the Forms ticket and proceed. If not, then you display the login page.

The only caveat is that since Windows authentication always sends a 401 response to the browser (challenging it for Windows credentials), then non-Domain users will always get a credentials pop-up that they will have to click Cancel on.

I used MVC in my project. My Windows login page is /Login/Windows and my manual login page is /Login.

Here are the relevant areas of my 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>

Here is my 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;
    }
}

Your Login View will just be a normal username / password form that does a POST to /Login.

At this point, you have a /Login page that people can manually go to to login. You also have a /Login/Windows page that is the default login page that people are automatically redirected to. But if Windows login fails, it'll display a generic 401 error page.

The key to making this seamless is using your Login view as your custom 401 error page. I did that by highjacking the response content in Application_EndRequest using the ViewRenderer class written by Rick Strahl.

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"));
}

Another caveat I've found is that this doesn't work in IIS Express (although it's been a version or two since I last tried). I have it setup in IIS and point the debugger at that.

这篇关于使用表单身份验证和Windows身份验证的Active Directory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆