本分步指南演示如何在 ASP.NET 应用程序如何使用窗体身份验证允许用户使用轻型目录访问协议 (LDAP),对 Active Directory 进行验证。经过身份验证的用户重定向之后,可以使用Application_AuthenticateRequest方法的 Global.asax 文件流动在整个请求的HttpContext.User属性中存储对象。

在 Visual C#.NET 创建 ASP.NET Web 应用程序

请按照以下步骤创建新的 ASP.NET Web 应用程序名为 FormsAuthAd Visual C#.NET 中:

  1. 启动 Microsoft Visual Studio.NET。
  2. 文件菜单上,指向新建,然后单击项目
  3. 单击项目类型下的Visual C# 项目,然后单击模板下的ASP.NET Web 应用程序
  4. 位置框中,替换为FormsAuthAdWebApplication1。
  5. 单击确定
  6. 用鼠标右键单击解决方案资源管理器中,在引用节点,然后单击添加引用
  7. 添加引用对话框中的.NET选项卡上,单击System.DirectoryServices.dll,单击选择,然后单击确定

编写验证代码

请按照下列步骤创建一个名为 LdapAuthentication.cs 的新类文件:

  1. 在解决方案资源管理器中,用鼠标右键单击项目节点,指向添加,然后单击添加新项
  2. 模板下,单击
  3. 在名称框中,键入LdapAuthentication.cs ,然后单击打开
  4. LdapAuthentication.cs 文件中的现有代码替换为以下代码。
    using System;
    using System.Text;
    using System.Collections;
    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属性。验证用户身份后, IsAuthenticated方法将返回true

若要获取该用户所属的组的列表,此代码将调用LdapAuthentication.GetGroups方法。LdapAuthentication.GetGroups方法获取安全和分发通过创建一个DirectorySearcher对象,并根据memberOf属性筛选用户所属的组的列表。此方法返回组的列表,用竖线 (|) 分隔。

请注意, LdapAuthentication.GetGroups方法操作,并将截断的字符串。这将减少身份验证 cookie 中存储的字符串的长度。如果该字符串不会被截断,每个组的格式如下所示。

CN=...,...,DC=domain,DC=com
				

这样可以创建一个很长的字符串。此字符串的长度大于该 cookie 的长度,如果浏览器不能接受的身份验证 cookie,并会将您重定向到登录页。但是,如果您是在多域环境中,您可能需要保留组名称的域名,因为在不同的域中的组可以有相同的组名。您必须保留域的名称来区分一组从另一个。

大多数浏览器支持达 4096 字节的 cookie。如果可能,此字符串可能会超过 cookie 的长度,您可以在 ASP.NET 缓存对象中或数据库中存储的组信息。或者,您可能希望组信息进行加密,并将此信息存储在一个隐藏的窗体字段。

编写 Global.asax 的代码

在 Global.asax 文件中的代码提供了一个Application_AuthenticateRequest事件处理程序。此事件处理程序从Context.Request.Cookies集合中检索身份验证 cookie,解密 cookie,并检索将FormsAuthenticationTicket.UserData属性中存储的组的列表。在 Logon.aspx 页中创建管道分隔的列表中显示的组。

代码分析的字符串中的字符串数组创建对象。对象创建后,此对象将位于HttpContext.User属性。

  1. 在解决方案资源管理器中,用鼠标右键单击Global.asax,然后单击查看代码
  2. 在代码隐藏 Global.asax.cs 文件的顶部添加以下代码:
    using System.Web.Security;
    using System.Security.Principal;
  3. 下面的代码为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 文件

在本节中,您可以配置< 窗体 >、 < 身份验证 >< 授权 >元素的 Web.config 文件中。进行这些更改,只有已通过身份验证的用户才能访问该应用程序,,未经身份验证的请求重定向到 Logon.aspx 页。您可以修改此配置为允许特定用户和组访问该应用程序。

在 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>

请注意< 标识模拟 ="true"/ >配置元素。这将导致 ASP.NET 模拟的帐户被配置为从 Microsoft Internet Information Services (IIS) 的匿名帐户。由于此配置中,对此应用程序的所有请求都运行的已配置帐户的安全上下文。用户提供的凭据以进行身份验证的 Active Directory,但访问 Active Directory 帐户配置的帐户。有关详细信息,请参阅参考部分。

将 IIS 配置为匿名身份验证

若要将 IIS 配置为匿名身份验证,请按照下列步骤操作:

  1. 在 IIS 中,展开计算机节点,为您的服务器,展开 网站、 展开 默认网站、 FormsAuthAd,用鼠标右键单击,然后单击属性
  2. 单击 目录安全性选项卡,然后单击 匿名访问和验证控件 下的 编辑
  3. 请为应用程序的匿名帐户具有活动目录的权限的帐户。
  4. 单击以清除允许 IIS 到控制密码复选框。
  5. 在身份验证的访问部分取消选中集成 Windows 身份验证复选框。
  6. 单击确定。
  7. 单击应用

默认 IUSR_ computername 的帐户不具有活动目录的权限。

创建 Logon.aspx 页

请按照下列步骤创建新 ASP.NET Web 窗体名为 Logon.aspx 操作:

  1. 在解决方案资源管理器中,用鼠标右键单击该项目节点,指向 添加,然后单击 添加 Web 窗体
  2. 在 名称 框中键入 Logon.aspx,然后单击 打开
  3. 在解决方案资源管理器中,用鼠标右键单击 Logon.aspx,然后单击 视图设计器
  4. 单击在设计器中的 HTML 选项卡。
  5. Replace the existing code with the following code.
    <%@ 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://corp.com"; //Fully-qualified Domain Name
    LdapAuthentication adAuth = new LdapAuthentication(adPath);
    try
    {
    if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
    {
    String groups = adAuth.GetGroups(); //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>
  6. 在修改路径 Logon.aspx 页,使其指向您 LDAP 目录服务器。

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

修改 WebForm1.aspx 页

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

  1. 在解决方案资源管理器中,用鼠标右键单击 WebForm1.aspx,然后单击 视图设计器
  2. 单击在设计器中的 HTML 选项卡。
  3. 将现有代码替换下面 code.
    <%@ 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>
  4. 保存所有的文件,然后编译该项目。
  5. 请求 WebForm1.aspx 页。请注意您将被重定向到 Logon.aspx。
  6. 键入登录凭据,然后单击 提交。当您将被重定向到 WebForm1.aspx 时,请注意,您的用户名出现和 $LdapAuthentication 是身份验证将类型为 Context.User.AuthenticationType 属性。

注意Microsoft 建议使用安全套接字层 (SSL) 加密时使用 Forms 身份验证。这是因为基于身份验证 cookie 标识用户,此应用程序上的 SSL 加密防止任何人危及安全的身份验证 cookie 和正在传输的任何其他有价值的信息。

参考

有关详细的信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

306590ASP.NET 安全性概述
317012在 ASP.NET 中的过程和请求身份
311495如何通过使用 Visual C#.net 在 ASP.NET 应用程序中实现基于窗体的身份验证与基于角色的安全性
313091如何创建通过使用 Visual Basic.net 在 Forms 身份验证中使用的键
313116窗体身份验证请求不被定向到 loginUrl 页

属性

文章编号: 316748 - 最后修改: 2007年10月16日 - 修订: 5.4
这篇文章中的信息适用于:
  • Microsoft Visual C# .NET 2003 标准版
  • Microsoft Visual C# .NET 2002 标准版
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
关键字:
kbmt kbconfig kbcookie kbhowtomaster kbsecurity kbwebforms KB316748 KbMtzh

如何通过使用窗体身份验证和 Visual C#.NET 对 Active Directory 验证身份的更多相关文章

  1. How to use the windows active directory to authenticate user via logon form 如何自定义权限系统,使用 active directory验证用户登录

    https://www.devexpress.com/Support/Center/Question/Details/Q345615/how-to-use-the-windows-active-dir ...

  2. HTTP 请求未经客户端身份验证方案“Anonymous”授权。从服务器收到的身份验证标头为“Negotiate,NTLM”

    转自:http://www.cnblogs.com/geqinggao/p/3270499.html 近来项目需要Web Service验证授权,一般有两种解决方案: 1.通过通过SOAP Heade ...

  3. 简化 Web 应用程序与 Windows Azure Active Directory、ASP.NET 和 Visual Studio 的集成

    大家好! 今天的博文深入讨论我们今天推出的开发人员工具和框架中的一些新功能.我们通过与 ASP.NET 和 Visual Studio 团队合作开发了一些重大的增强功能,让开发人员能够轻松使用 Win ...

  4. Windows Azure Active Directory (1) 前言 - 基于声明的验证和授权

    <Windows Azure Platform 系列文章目录> 在我们介绍整套系统架构之前,我们需要首先定义一些基本的概念. 用户及其属性: 用户值得是要使用某项服务的个体.用户一般都有一 ...

  5. kpvalidate开辟验证组件,通用Java Web请求服务器端数据验证组件

    小菜利用工作之余编写了一款Java小插件,主要是用来验证Web请求的数据,是在服务器端进行验证,不是简单的浏览器端验证. 小菜编写的仅仅是一款非常初级的组件而已,但小菜为它写了详细的说明文档. 简单介 ...

  6. JS表单验证-12个常用的JS表单验证

    JS表单验证-12个常用的JS表单验证 最近有个项目用到了表单验证,小编在项目完结后的这段时间把常用的JS表单验证demo整理了一下,和大家一起分享~~~ 1. 长度限制 <p>1. 长度 ...

  7. Asp.net MVC验证那些事(1)-- 介绍和验证规则使用

    数据的有效性验证,是程序开发中必不可少的环节.这篇文章,我们将用一个实例来说明如何在MVC中使用Validation来保证无论是新增或者更新数据的时候,都必须符合我们定义的验证规则,否则就会提示错误. ...

  8. (转)[jQuery]使用jQuery.Validate进行客户端验证(初级篇)——不使用微软验证控件的理由

    以前在做项目的时候就有个很大心病,就是微软的验证控件,虽然微软的验证控件可以帮我们完成大部分的验证,验证也很可靠上手也很容易,但是我就是觉得不爽,主要理由有以下几点: 1.拖控件太麻烦,这个是微软控件 ...

  9. 采用truelicense进行Java规划license控制 扩展可以验证后,license 开始结束日期,验证绑定一个给定的mac住址

    采用truelicense进行Java规划license控制 扩展可以验证后,license 开始结束日期,验证绑定一个给定的mac住址. Truelicense 它是一个开源java license ...

随机推荐

  1. Android百日程序 开篇章:Intent打开网页

    学习一下人家100日写100个网页的做法,我也用100日写100个完整的Android程序. 这些程序的最基本要求: 1 完整性-每一个程序都必须是独立可执行的 2 不反复性-所用的重点知识点都不一样 ...

  2. Unity创建一个简易的弹簧(弹动)效果

    参考文章:http://www.cnblogs.com/SkyD/archive/2008/09/05/1284778.html 主要依据胡克公式F=-k·x.这里k是倔度系数,可以理解为k值越大弹性 ...

  3. xcode代码没颜色的解决方案

    转自:http://blog.csdn.net/jiarusun000/article/details/7527631 今天代码使用了svn后发现项目中的所有原文件都没颜色了... 查找半天后发现是因 ...

  4. 读取JPG图片的Exif属性(一) - Exif信息简介

    https://blog.csdn.net/fioletfly/article/details/53605959 https://blog.csdn.net/a_big_pig/article/det ...

  5. 使用tar命令解压的时候报错not in gzip format

    使用tar命令解压一个xx.tar.gz压缩包的时候报错not in gzip format,后用file xx.tar.gz查看一下格式发现是html document text格式的...

  6. vscode 换行符\n 变成\r\n

    VSCode是一个开源的强大代码编写器,但是如果没有好好的配置使用,会适得其反. 这里总结VSCode的一些配置,方便自己查询,也方便网友. 1.编辑器配置 为特定类型文件指定缩进大小.缩进类型(空格 ...

  7. DIOCP-开源项目ECHO测试.

    DIOCP自开源以来,得到了很多朋友的测试,并进行了诸多的改进,现在已经运用到了一些具体的项目当中. DIOCP底层运行稳定. 昨天做了个ECHO测试,这个连接数并没有达到上限. 11K 连接,1个半 ...

  8. LeetCode: Best Time to Buy and Sell Stock II 解题报告

    Best Time to Buy and Sell Stock IIQuestion SolutionSay you have an array for which the ith element i ...

  9. vi卡死解决办法

    玩了这么多年linux 居然不知道这个..特此记录. 使用vim时,如果你不小心按了 Ctrl + s后,你会发现不能输入任何东西了,像死掉了一般,其实vim并没有死掉,这时vim只是停止向终端输出而 ...

  10. Android背景颜色渐变

    ●使用XML的方式为背景添加渐变效果 1.在res/drawable文件夹里添加一个jbshape.xml文件,然后写入如下代码: <?xml version="1.0" e ...