本分步指南演示如何在 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. Atitit 找人软福利建设 技术团队建设大概流程

    Atitit 找人软福利建设 技术团队建设大概流程 火车公司有免费车座,餐馆有免费饭吃.. 软件公司嘛,就是软件资源,知识了...技术... 培训体系 大概的知识库体系..让他知道来到我们团队有着很高 ...

  2. testbench的设计 文件读取和写入操作 源代码

    十大基本功之 testbench 1. 激励的产生 对于 testbench 而言,端口应当和被测试的 module 一一对应.端口分为 input,output 和 inout 类型产生激励信号的时 ...

  3. 最新Windows下c++读写锁SRWLock介绍

    https://blog.csdn.net/MoreWindows/article/details/7650574 https://blog.csdn.net/chenzhjlf/article/de ...

  4. sql server获取时间格式

    在本文中,GetDate()获得的日期由两部分组成,分别是今天的日期和当时的时间: Select GetDate()  用DateName()就可以获得相应的年.月.日,然后再把它们连接起来就可以了: ...

  5. 【JS设计模式】温习简单工厂模式、工厂方法模式、抽象工厂模式概念

    注:空心箭头表示的是种继承关系,工厂类和产品类之间是一种依赖关系.是用箭头加虚线表示的,以下的模型图是用的实线是不正确(时间不够用,在这里我偷懒了.这个习惯不好,呵呵) 简单工厂模式(Simple F ...

  6. schema中字段类型的定义

    当schema中字段类型为String时,保存的时候如果该字段为Number也可以保存成功,mongoose会自动将其转换为数字字符串. 当schema中字段类型为Number时,保存的时候如果该字段 ...

  7. (原创)c++11改进我们的模式之改进表驱动模式

    所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值.表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里.对于消除 ...

  8. GDB 调试解析

    GDB(GNU Debugger)是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序 列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优 ...

  9. VirtualBox虚拟机网络环境解析和搭建-NAT、桥接、Host-Only、Internal、端口映射

    一.NAT模式 特点: 1.如果主机可以上网,虚拟机可以上网 2.虚拟机之间不能ping通 3.虚拟机可以ping通主机(此时ping虚拟机的网关,即是ping主机) 4.主机不能ping通虚拟机 应 ...

  10. UNIX环境高级编程 apue.h头文件的配置

    http://jimslinbing.blog.163.com/blog/static/85054319201292712414518/ 1.到http://www.apuebook.com下载源码2 ...