`

从 ASP .NET 进行 Active Directory 域服务身份验证

 
阅读更多
从 ASP .NET 进行 Active Directory 域服务身份验证
本主题说明 ASP.NET 应用程序如何使用 Forms 身份验证来允许用户使用轻型目录访问协议 (LDAP) 对 Active Directory 域服务进行身份验证。在对用户进行身份验证和重定向后,可以使用 Global.asax 文件的 Application_AuthenticateRequest 方法在 HttpContext.User 属性中存储 GenericPrincipal 对象(该对象贯穿整个请求)。

创建新的 ASP.NET Web 应用程序
启动 Microsoft Visual Studio .NET。

在“文件”菜单上,指向“新建”,然后单击“项目”。

在“项目类型”下,单击“Visual C# 项目”,然后在“模板”下单击“ASP.NET Web 应用程序”。

在“名称”框中,键入 FormsAuthAd。

如果您使用的是本地服务器,则在“服务器”框中保留默认的 http://localhost。否则,添加指向您所用服务器的路径。单击“确定”。

在“解决方案资源管理器”中,右键单击“引用”节点,然后单击“添加引用”。

在“添加引用”对话框中的 .NET 选项卡上,依次单击 System.DirectoryServices.dll、“选择”和“确定”。

添加 System.DirectoryServices 身份验证代码
在“解决方案资源管理器”中,右键单击项目节点,指向“添加”,然后单击“添加新项”。

在“模板”下,单击“类”。

在“名称”框中键入 LdapAuthentication.cs,然后单击“打开”。

用下面的代码替换 LdapAuthentication.cs 文件中的现有代码:

using System;
using System.Text;
using System.Collections;
using System.Web.Security;

using System.Security.Principal;   
using System.DirectoryServices;


namespace FormsAuth
{
  public class LdapAuthentication
  {
    private string _path;
    private string _filterAttribute;

    public LdapAuthentication(string path)
    {
      _path = path;
    }

    public bool IsAuthenticated(string domain, string username, string pwd)
    {
      string domainAndUsername = domain + @"/" + username;
      DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);

      try
      {
        //Bind to the native AdsObject to force authentication.
        object obj = entry.NativeObject;

        DirectorySearcher search = new DirectorySearcher(entry);

        search.Filter = "(SAMAccountName=" + username + ")";
        search.PropertiesToLoad.Add("cn");
        SearchResult result = search.FindOne();

        if(null == result)
        {
          return false;
        }

        //Update the new path to the user in the directory.
        _path = result.Path;
        _filterAttribute = (string)result.Properties["cn"][0];
      }
      catch (Exception ex)
      {
        throw new Exception("Error authenticating user. " + ex.Message);
      }

      return true;
    }

    public string GetGroups()
    {
      DirectorySearcher search = new DirectorySearcher(_path);
      search.Filter = "(cn=" + _filterAttribute + ")";
      search.PropertiesToLoad.Add("memberOf");
      StringBuilder groupNames = new StringBuilder();

      try
      {
        SearchResult result = search.FindOne();
        int propertyCount = result.Properties["memberOf"].Count;
        string dn;
        int equalsIndex, commaIndex;

        for(int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
        {
          dn = (string)result.Properties["memberOf"][propertyCounter];
       equalsIndex = dn.IndexOf("=", 1);
          commaIndex = dn.IndexOf(",", 1);
          if(-1 == equalsIndex)
          {
            return null;
          }
          groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
          groupNames.Append("|");
        }
      }
    catch(Exception ex)
    {
      throw new Exception("Error obtaining group names. " + ex.Message);
    }
    return groupNames.ToString();
  }
}
}
在前面的过程中,身份验证代码接受域、用户名、密码和指向 Active Directory 域服务中的树的路径。此代码使用 LDAP 目录提供程序。Logon.aspx 页中的代码调用 LdapAuthentication.IsAuthenticated 方法并传入从该用户收集的凭据。然后,创建一个 DirectoryEntry 对象,该对象包含指向目录树的路径、用户名和密码。用户名必须采用“域/用户名”格式。

然后,DirectoryEntry 对象通过获取 NativeObject 属性,尝试强制绑定 AdsObject。如果上述操作成功,则通过创建 DirectorySearcher 对象并按 sAMAccountName 进行筛选,获取用户的 CN 属性。有关 Active Directory 域服务架构中 有关 sAMAccountName 的详细信息,请参阅 MSDN Library 中的“sAMAccountName”或“SAM-Account-Name attribute(SAM-Account-Name 属性)”。在对用户进行身份验证后,IsAuthenticated 方法返回 true。为获取用户所属的组列表,此代码调用 LdapAuthentication.GetGroups 方法。LdapAuthentication.GetGroups 方法通过创建 DirectorySearcher 对象并根据 memberOf 属性进行筛选,获取用户所属的安全和通讯组的列表。有关 Active Directory 域服务架构中 有关 memberOf 的详细信息,请参阅 MSDN Library 中的“memberOf”或“Is-Member-Of-DL attribute(Is-Member-Of-DL 属性)”。此方法返回由竖线 (|) 分隔的组列表。请注意,LdapAuthentication.GetGroups 方法会对字符串进行截断处理。这将缩短在身份验证 cookie 中存储的字符串的长度。如果字符串未被截断,则每组的格式将按如下显示:

CN=...,...,DC=domain,DC=com
LdapAuthentication.GetGroups 方法可能返回非常长的字符串。如果此字符串的长度大于 cookie 的长度,可能不会创建身份验证 cookie。如果此字符串可能超出 cookie 的长度,则您可能需要在 ASP.NET 缓存对象或数据库中存储组信息。或者,您可能需要对组信息进行加密,并在隐藏的窗体域中存储此信息。

Global.asax 文件中的代码提供 Application_AuthenticateRequest 事件处理程序。此事件处理程序从 Context.Request.Cookies 集合检索身份验证 cookie,对 cookie 进行解密,并且检索将在 FormsAuthenticationTicket.UserData 属性中存储的组的列表。这些组显示在 Logon.aspx 页中创建的、用竖线分隔的列表中。代码对字符串数组中的字符串进行分析,以创建 GenericPrincipal 对象。在创建 GenericPrincipal 对象后,将该对象放置于 HttpContext.User 属性中。

编写 Global.asax 代码
在“解决方案资源管理器”中,右键单击 Global.asax,然后单击“查看代码”。

将以下代码添加到 Global.asax.cs 文件的代码隐藏的顶部:

using System.Web.Security;
using System.Security.Principal;
使用以下代码替换 Application_AuthenticateRequest 的现有空事件处理程序:

void Application_AuthenticateRequest(object sender, EventArgs e)
{
  string cookieName = FormsAuthentication.FormsCookieName;
  HttpCookie authCookie = Context.Request.Cookies[cookieName];

  if(null == authCookie)
  {
    //There is no authentication cookie.
    return;
  }
  FormsAuthenticationTicket authTicket = null;
  try
  {
    authTicket = FormsAuthentication.Decrypt(authCookie.Value);
  }
  catch(Exception ex)
  {
    //Write the exception to the Event Log.
    return;
  }
if(null == authTicket)
  {
    //Cookie failed to decrypt.
    return;
  }
  //When the ticket was created, the UserData property was assigned a
  //pipe-delimited string of group names.
  string[] groups = authTicket.UserData.Split(new char[]{'|'});
  //Create an Identity.
  GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");
  //This principal flows throughout the request.
  GenericPrincipal principal = new GenericPrincipal(id, groups);
  Context.User = principal;
}
在本节中,您将配置 Web.config 文件中的 <forms>、<authentication> 和 <authorization> 元素。通过这些更改,只有经过了身份验证的用户才能访问该应用程序,并且未经身份验证的请求将被重定向到 Logon.aspx 页。您可以修改此配置,以便只允许某些用户和组访问该应用程序。

修改 Web.config 文件
在记事本中打开 Web.config。

用下面的代码替换现有代码:

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/"> </forms> </authentication> <authorization> <deny users="?"/> <allow users="*"/> </authorization> <identity impersonate="true"/> </system.web> </configuration>
请注意以下配置元素:

<identity impersonate="true"/>
对于配置为来自 Microsoft Internet 信息服务 (IIS) 的匿名帐户的帐户,上述元素将导致 ASP.NET 模拟该帐户。此配置导致的结果是,对此应用程序的所有请求都基于所配置的帐户的安全上下文运行。该用户提供凭据以针对 Active Directory 域服务进行身份验证,但访问 Active Directory 域服务的帐户是已配置的帐户。

为匿名身份验证配置 IIS
在 IIS 管理器(在“管理工具”中)或用于 IIS 的 MMC 管理单元中,右键单击您要为其配置身份验证的网站,然后单击“属性”。

单击“目录安全性”选项卡,然后在“身份验证和访问控制”下,单击“编辑”。

选中“匿名身份验证”复选框(在 Windows Server 2003 中标记为“启用匿名访问”)。

使应用程序的匿名帐户成为对 Active Directory 域服务具有权限的帐户。

如果启用了“允许 IIS 控制密码”复选框,则清除该复选框。默认的 IUSR_<computername> 帐户对 Active Directory 域服务不具有权限。

创建 Logon.aspx 页
在“解决方案资源管理器”中,右键单击项目节点,指向“添加”,然后单击“添加 Web 窗体”。

在“名称”框中,键入 Logon.aspx,然后单击“打开”。

在“解决方案资源管理器”中,右键单击 Logon.aspx,然后单击“视图设计器”。

单击“设计器”中的“HTML”选项卡。

用下面的代码替换现有代码:

<%@ Page language="c#" AutoEventWireup="true" %> <%@ Import Namespace="FormsAuth" %> <html> <body> <form id="Login" method="post" runat="server"> <asp:Label ID="Label1" Runat=server >Domain:</asp:Label> <asp:TextBox ID="txtDomain" Runat=server ></asp:TextBox><br> <asp:Label ID="Label2" Runat=server >Username:</asp:Label> <asp:TextBox ID=txtUsername Runat=server ></asp:TextBox><br> <asp:Label ID="Label3" Runat=server >Password:</asp:Label> <asp:TextBox ID="txtPassword" Runat=server TextMode=Password></asp:TextBox><br> <asp:Button ID="btnLogin" Runat=server Text="Login" OnClick="Login_Click"></asp:Button><br> <asp:Label ID="errorLabel" Runat=server ForeColor=#ff3300></asp:Label><br> <asp:CheckBox ID=chkPersist Runat=server Text="Persist Cookie" /> </form> </body> </html> <script runat=server> void Login_Click(object sender, EventArgs e) { string adPath = "LDAP://" + txtDomain.Text; LdapAuthentication adAuth = new LdapAuthentication(adPath); try { if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) { string groups = adAuth.GetGroups(txtDomain.Text, txtUsername.Text, txtPassword.Text); //Create the ticket, and add the groups. bool isCookiePersistent = chkPersist.Checked; FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups); //Encrypt the ticket. string encryptedTicket = FormsAuthentication.Encrypt(authTicket); //Create a cookie, and then add the encrypted ticket to the cookie as data. HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); if(true == isCookiePersistent) authCookie.Expires = authTicket.Expiration; //Add the cookie to the outgoing cookies collection. Response.Cookies.Add(authCookie); //You can redirect now. Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false)); } else { errorLabel.Text = "Authentication did not succeed. Check user name and password."; } } catch(Exception ex) { errorLabel.Text = "Error authenticating. " + ex.Message; } } </script>
修改 Logon.aspx 页中的路径,以指向您的 LDAP 目录服务器。

Logon.aspx 页是一个用于收集来自用户的信息并调用 LdapAuthentication 类上的方法的页面。在代码对用户进行身份验证并获取了组列表后,该代码创建一个 FormsAuthenticationTicket 对象,对票证进行加密,向一个 cookie 添加加密的票证,向 HttpResponse.Cookies 集合添加该 cookie,然后将请求重定向到最初请求的 URL。

WebForm1.aspx 页是最初请求的页。在用户请求此页时,请求被重定向到 Logon.aspx 页。在对请求进行身份验证后,该请求被重定向到 WebForm1.aspx 页。

修改 WebForm1.aspx 页
在“解决方案资源管理器”中,右键单击 WebForm1.aspx,然后单击“视图设计器”。

单击“设计器”中的“HTML”选项卡。

用下面的代码替换现有代码:

<%@ Page language="c#" AutoEventWireup="true" %> <%@ Import Namespace="System.Security.Principal" %> <html> <body> <form id="Form1" method="post" runat="server"> <asp:Label ID="lblName" Runat=server /><br> <asp:Label ID="lblAuthType" Runat=server /> </form> </body> </html> <script runat=server> void Page_Load(object sender, EventArgs e) { lblName.Text = "Hello " + Context.User.Identity.Name + "."; lblAuthType.Text = "You were authenticated using " + Context.User.Identity.AuthenticationType + "."; } </script>
保存所有文件,然后编译该项目。

请求 WebForm1.aspx 页。请注意,您将被重定向到 Logon.aspx。

键入登录凭据,然后单击“提交”。在您重定向到 WebForm1.aspx 后,请注意,您的用户名将出现并且 LdapAuthentication 是用于 Context.User.Identity.AuthenticationType 属性的身份验证类型。

注意:
建议您在使用窗体身份验证时使用安全套接字层 (SSL) 加密。这是因为用户是基于身份验证 cookie 标识的;所以,对此应用程序进行 SSL 加密将防止任何人损害传输的身份验证 cookie 以及任何其他重要信息。
分享到:
评论

相关推荐

    【ASP.NET编程知识】asp.net身份验证方式介绍.docx

    它还用在必须对 Windows NT 系统进行身份验证的混合 Windows 2000 Active Directory 域环境中。NTLM 身份验证机制使用质询/应答机制来验证用户的身份。 Kerberos v5 身份验证 Kerberos v5 身份验证是 ASP.NET 中的...

    asp.net 实现用户的域验证

    总之,ASP.NET中的用户域验证是一个关键的安全特性,通过结合Forms身份验证和ActiveDirectoryMembershipProvider,我们可以确保只有特定域内的用户能够访问我们的Web应用。通过以上步骤,你可以有效地保护你的应用...

    活动目录Active Directory 管理工具

    在Windows Server上,管理员可以使用Active Directory域服务来构建一个或多个逻辑组织结构,称为域。每个域都是一个独立的安全边界,拥有自己的用户账户和计算机账户。当用户登录到域中的一台计算机时,他们的身份由...

    CAS的ASP.NET客户端配置及验证

    在ASP.NET中配置CAS客户端,首先需要安装相应的库,如`Microsoft.IdentityModel.Clients.ActiveDirectory`或`DotNetCasClient`。后者是一个专门为.NET Framework设计的CAS客户端库,可以简化配置和集成过程。 1. **...

    ASP.NET聊天室

    ASP.NET是一种由微软开发的服务器端Web...综上所述,这个ASP.NET聊天室项目涵盖了身份验证、实时通信、文件上传、数据库操作、并发处理、前端开发等多个IT领域的核心知识点,是一个全面展示ASP.NET开发能力的实践案例。

    Asp.Net Core中基于Session的身份验证的实现

    1. **Windows身份验证**:通常用于企业内部环境,依赖于Windows Active Directory进行身份验证,适用于Windows平台上的内部网络应用。 2. **Forms身份验证**:Asp.Net框架中的另一种验证方式,它允许开发者自定义...

    使用Azure Active Directory和OpenID Connect在ASP.NET Core 2.0中进行身份验证和授权

    本文将深入探讨如何利用Azure Active Directory(Azure AD)和OpenID Connect在ASP.NET Core 2.0框架中实现这一目标。Azure AD是一种云身份管理解决方案,它允许开发人员构建安全的应用程序并连接到全球数百万个组织...

    ASP.NET 登陆窗口例子

    在这个“ASP.NET 登录窗口例子”中,我们将探讨如何在ASP.NET环境中实现用户登录功能,以及如何与Access数据库进行交互来存储和验证用户信息。 首先,ASP.NET登录窗口是应用程序中的关键组件,它允许用户输入他们的...

    asp.net SSO 单点登录

    ASP.NET SSO(Single Sign-On)单点登录是一种网络身份验证机制,允许用户在一个应用系统中登录后,无须再次输入凭证即可访问其他相互信任的应用系统。这种技术极大地提升了用户体验,减少了频繁输入用户名和密码的...

    ASP.NET 2.0安全系列课程:ASP.NET Web form验证入门

    - **Windows身份验证**:基于Windows操作系统提供的安全服务进行身份验证。 - **Passport身份验证**:利用Microsoft Passport网络服务实现跨站点的身份验证。 - **Web Form身份验证**:使用自定义的用户名和密码进行...

    asp.net WEB.CONFIG form验证

    在本例中,我们关注的是"ASP.NET WEB.CONFIG form验证",这指的是使用Form身份验证(Forms Authentication)的方式进行用户验证,这是一种常见的ASP.NET安全实践。 Form验证是ASP.NET提供的一种内置的身份验证机制...

    asp.net的登陆控件

    在ASP.NET框架中,登录控件(Login Control)是预定义的服务器控件之一,旨在简化网站用户身份验证的过程。在本项目中,你将学习如何使用这些控件以及它们的基本功能。 首先,登录控件的核心在于其内置的身份验证...

    ActiveDirectory.zip

    根据标签"AD ActiveDirectory C# javascript",我们可以推断,这个项目使用C#作为后端语言,利用ASP.NET框架构建Web服务,同时使用JavaScript进行前端交互设计。 C#是一种强大的面向对象的编程语言,特别适合开发...

    ASP.NET Core.pdf.pdf

    教程涵盖了使用Azure Active Directory(AAD)、AAD B2C、IdentityServer等实现身份验证和授权的方法。开发者还可以利用授权视图(AuthorizeView)和角色管理来控制应用的访问权限。 部署和测试方面,ASP.NET Core...

    PB 转ASP.net入门简单登录页面

    3. **身份验证机制**:ASP.NET提供了多种身份验证方法,如 Forms Authentication,它可以将用户的凭据与数据库中的记录进行比较,或者使用Active Directory等外部源进行验证。 4. **错误处理**:如果登录失败,需要...

    ASP.NET应用教程

    ASP.NET Identity可以与多种存储后端集成,如SQL Server、Azure Active Directory或OAuth提供者。 6. **Web API**:ASP.NET中的Web API组件用于构建RESTful服务,允许开发API供其他应用或客户端(如移动设备)使用...

    asp.net登录模块

    ASP.NET登录模块是Web应用程序开发中的关键组成部分,它允许用户进行身份验证并控制对网站资源的访问。在ASP.NET框架中,内置的安全机制为开发者提供了创建安全登录功能的强大工具。以下是对这个登录模块实例的详细...

    asp.net vb 后台登陆例子

    这通常涉及到SQL查询或者使用更安全的身份验证服务,如Active Directory或ASP.NET Identity。 3. **数据连接**:为了访问数据库,你需要配置数据库连接字符串,并使用ADO.NET库(如`SqlConnection`和`SqlCommand`)...

    构建安全的ASP.NET

    如何做:将表单身份验证用于 Active Directory.doc 如何做:将表单身份验证用于 GenericPrincipal 对象.doc 如何做:将表单身份验证用于 SQL Server 2000.doc 如何做:设置客户端证书.doc 微软.Net程序设计FAQ.doc

Global site tag (gtag.js) - Google Analytics