MVC 5 C#Web App使用针对AD的表单或Windows身份验证

时间:2014-10-07 22:08:29

标签: c# authentication asp.net-mvc-5

我有一个MVC5应用程序正在使用针对AD的表单身份验证。我希望能够使用Windows身份验证,如果用户已经在他们的计算机上登录到AD,如果没有进入表单身份验证,他们可以输入他们的AD凭据。

在没有编写自定义成员资格类的情况下,是否有相对直接的方法来处理此问题?如果是这样怎么样?任何帮助,将不胜感激。我看过几篇关于不混合身份验证类型的帖子,但我没有使用任何本地身份验证。这一切都是针对AD的。这仍然不受支持吗?

1 个答案:

答案 0 :(得分:1)

IIS在技术上不支持(如果这是您正在使用的),但您可以启用表单和Windows身份验证。

在表单身份验证设置的“loginUrl”中使用的任何控制器中(在Web.config中),您可以检查标头以确定用户是否已登录,例如:

鉴于此设置

<forms loginUrl="~/Login">

你可以这样做:

public class LoginController: Controller
{
    public ActionResult Index()
    {
        string windowsUserName = Request.ServerVariables["LOGON_USER"];
        if (!string.IsNullOrEmpty(windowsUserName))
        {
            Regex regex = new Regex(@"(^\w+)\\", RegexOptions.IgnoreCase);
            string userName = regex.Replace(windowsUserName, string.Empty);

            // validate the user name against ad here

            FormsAuthentication.SetAuthCookie(userName, false);

            this.RedirectToAction("Index", "Home");
        }
        else
        {
            // if the user isn't signed in with AD credentials you can send an
            // "unauthorized" http code and the browser (excluding Firefox)
            // will try to send credentials (if available).

            // you will have to manage staying out of a redirect loop
            // many options here: set and check a cookie, session, headers, etc.
            return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
        }
    }
}
  1. 匿名(未经身份验证的)请求命中LoginController
    • 系统发送未经授权的http响应
  2. 经过身份验证的请求会访问LoginController
    • 系统检查标题并将值与AD进行比较(下面与AD比较的示例)
  3. 当我必须为特定应用程序执行此操作时,我还检查了请求主机地址(以确保它与服务器位于同一域中,否则我甚至不打扰:

    IPAddress address = null;
    
    if (IPAddress.TryParse(Request.UserHostAddress, out address))
    {
        if (IPAddress.IsLoopback(address))
        {
            address = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(ip => !IPAddress.IsLoopback(ip));
            if (address == null)
            return View();
        }
    
        IPHostEntry entry = Dns.GetHostEntry(address);
    
        bool isPartOfDomain = false;
    
        foreach (IPAddress hostEntryAddress in entry.AddressList)
        {
            if (String.Equals(address.ToString(), hostEntryAddress.ToString()))
            {
                string domain = "Your Domain Here"; // or get it from your configuration settings / db / etc
    
                using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domain))
                {
                    string computerName = entry.HostName.Replace("." + domain, string.Empty);
    
                    using (ComputerPrincipal computer = ComputerPrincipal.FindByIdentity(domainContext, computerName))
    
                     if (computer != null)
                    {
                        isPartOfDomain = true;
                        break;
                    }
                }
            }
        }
    }
    

    我通常会检查域PrincipalContext以验证用户名。

    DirectoryEntry entry;
    string domain = "Your Domain Here",
           userName = "Some User Name";
    
            using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain))
            {
                using (UserPrincipal principal = UserPrincipal.FindByIdentity(context, userName))
                {
                    if (principal != null && (entry = (DirectoryEntry)principal.GetUnderlyingObject()) != null)
                    {
                        string userPrincipalName = principal.UserPrincipalName ?? principal.Name;
                        userPrincipalName = userPrincipalName.Substring(0, (userPrincipalName.Contains("@") ? userPrincipalName.IndexOf("@") : userPrincipalName.IndexOf(" ")));
    
                        bool isValid = string.Equals(userName, userPrincipalName);
                    }
                }
            }