在ASP.NET MVC中使用Active Directory进行身份验证

4
我希望能够在我的asp.net mvc项目中使用活动目录对用户进行身份验证。经过数小时的上网搜索,我并没有找到对我有用的东西。我已经看了所有结果,但是什么都没有。
我尝试按照很多帖子建议编辑我的web.config文件。
如果有人能够提供一些代码片段或示例来帮助我,我将不胜感激,因为我不知道从哪里开始。
编辑
我的当前web.config文件。
<system.web>
<authentication mode="Forms">
  <forms name=".ADAuthCookie" loginUrl="~/MainMenu/Login" timeout="45" 
 slidingExpiration="false" protection="All" />
</authentication>
<authorization>
  <deny users="?" />
</authorization>
<membership defaultProvider="ADMembershipProvider">
  <providers>
    <clear />
     <add name="ADMembershipProvider" 
     type="System.Web.Security.ActiveDirectoryMembershipProvider"  
     connectionStringName="ADConnectionString" 
     attributeMapUsername="sAMAccountName" />
  </providers>
</membership>
</system.web>      
<connectionStrings>
 <add name="ADConnectionString" 
   connectioString="LDAP://myserver.mydomain.COM:389/DC=mydomain,DC=COM" />
</connectionStrings>

Leo

Ciao Leo,看看这个Stackoverflow帖子。你只需要设置<authentication mode="Windows" />即可。 - Max
@Max发布的评论应该可以解决您的问题。不过,您是否想要对用户提交的凭据进行活动目录身份验证? - Gagan Deep
@Max 只需要添加标签吗?不需要其他代码吗?比如控制器、视图等等? - Leonardo Bassi
@Max,我需要向用户询问用户名和密码,因为并非每个人都可以进入某些部分。 - Leonardo Bassi
在这种情况下,您需要在应用程序中维护用户和角色表,并仅对用户发布的凭据进行AD身份验证。我将在答案中提供用于对AD进行身份验证的代码。 - Gagan Deep
显示剩余2条评论
3个回答

3
我这样设置视图模型和控制器解决了我的问题:
模型
public class LogOnModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}

控制器
public class AccountController : Controller
{
    public ActionResult LogOn()
    {
        return View();
    }

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Main", "MainMenu");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect");
            }
        }

        // if we got this far, something failed, redisplay form
        return View(model);
    }

    public ActionResult LogOff()
    {
        FormsAuthentication.SignOut();

        return RedirectToAction("Login", "Account");
    }

View

<body id="bodyMain">
@using (Html.BeginForm("LogOn", null,FormMethod.Post))
{
<div class="container">
    @Html.ValidationSummary(true, "")
    <div style="padding-top:30%"></div>
    <table>
        <tr>
            <td>@Html.EditorFor(model => model.UserName)</td>
            <td>@Html.ValidationMessageFor(model => model.UserName, "",)</td>
        </tr>
        <tr></tr>
        <tr>
            <td>@Html.EditorFor(model => model.Password)</td>
            <td>@Html.ValidationMessageFor(model => model.Password, "")</td>
        </tr>
        <tr>
            <td>@Html.CheckBoxFor(model=>model.RememberMe)</td>               
        </tr>
    </table>
    <br />
    <button type="submit" class="btn btn-info">Login</button>
</div>
}

"而且 web.config 与我的问题保持不变"

1
正如评论中所提到的,只需将您的身份验证方式从Forms更改为Windows即可。
<authentication mode="Windows" />

如果运行此代码的服务器加入了用户登录到的相同域或信任域,则此方法可行。只要您的网站设置为受信任的站点(通常是内部网站),用户就不会被提示登录。

要限制应用程序的某些部分,可以使用 AuthorizeAttribute。例如,限制访问某个 AD 组的成员:

[Authorize(Roles="DOMAIN\GroupName")]

或者,限制访问特定的AD用户:
[Authorize(Users="DOMAIN\UserName")]

通过逗号分隔可以添加多个角色或用户:

[Authorize(Roles="DOMAIN\Group1, DOMAIN\Group2")]

这些属性可以应用于整个控制器,或单独的操作。

更多信息在此处


我有点困惑,但是我需要一种表单,用户必须在其中输入他的用户名和密码,在验证凭据之后,用户只能浏览某些部分,例如查看某些内容的详细信息,但不能编辑,例如:示例用户,而管理员可以做任何事情。一种后端方式,允许指定哪些域用户可以访问具有特定权限的特定域。 - Leonardo Bassi
只有在您的服务器未加入与用户(或受信任的用户)相同的域时,才需要使用用户必须输入其用户名和密码的表单。这是您的情况吗? - Gabriel Luci
不,我的计算机加入了服务器的同一域。 - Leonardo Bassi
然后使用Windows身份验证 :) 这将使您的生活变得更加轻松。它会为您验证他们的凭据,您只需使用[Authorize]属性来锁定您需要的控制器或操作即可。 - Gabriel Luci
很好,但经过一些考虑,我得出结论需要使用不同的用户或PC登录到网站,而这些用户或PC并不在域中。如果您有任何想法可以告诉我从哪里开始,我将不胜感激 :) - Leonardo Bassi
那个比较困难。你可以选择将所有内容都设置为表单验证并自己验证人们的AD凭据,或者使用分离的表单/Windows身份验证,允许那些拥有域帐户的用户自动登录,否则需要输入凭据。 - Gabriel Luci

1
如果需要对用户提交的用户名和密码进行与AD的身份验证,请使用下面的代码。
添加对System.DirectoryServices.AccountManagement的引用。
在代码文件中:
using System.DirectoryServices.AccountManagement;

接下来,在你的POST方法中(flag是布尔类型变量)
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "DOMAINNAME");
            flag = pc.ValidateCredentials(UserName, Password);

如果标志为真,则凭据有效,否则无效。
在这种情况下,您需要手动设置用户和角色(使用表单身份验证),然后可以通过使用来限制用户/角色显示控制器/视图
[Authorize(Roles="RoleName")]

这段代码是用于控制器的对吗?它从我的登录视图接收了用户名和密码的POST请求,这种方法正确吗? - Leonardo Bassi
你好,这篇文章已经有些年头了,但我希望你能够澄清一些事情。在我的情况下,如果我使用没有用户名和密码的构造函数,身份验证总是失败的。如果我使用 new PrincipalContext(ContextType.Domain, "DOMAINNAME", ContextOptions.Negotiate, userName, password),那么我可以立即调用 UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, userName);。如果用户名或密码不正确,FindByIdentity 将抛出异常。如果它们是正确的,我就可以继续进行其余的流程,例如设置声明。为什么会这样呢? - jstuardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接