フォーム認証と Visual Basic .NET を使用して Active Directory に対する認証を行う方法

概要
この資料では、ASP.NET アプリケーションでフォーム認証を使用して、ユーザーが LDAP (Lightweight Directory Access Protocol) を使用して Active Directory に対する認証を行えるようにする方法について、手順を追って説明します。

ユーザーが認証されてリダイレクトされた後は、Global.asax ファイルの Application_AuthenticateRequest メソッドを使用して、要求全体にわたって使用される GenericPrincipal オブジェクトを HttpContext.User プロパティに格納することができます。

Visual Basic .NET で ASP.NET Web アプリケーションを作成する

以下の手順を実行して、Visual Basic .NET で FormsAuthAd という名前の ASP.NET Web アプリケーションを新規に作成します。
  1. Microsoft Visual Studio .NET を起動します。
  2. [ファイル] メニューの [新規作成] をポイントして、[プロジェクト] をクリックします。
  3. [プロジェクトの種類] の [Visual Basic プロジェクト] をクリックして、[テンプレート] の [ASP.NET Web アプリケーション] をクリックします。
  4. [場所] ボックスに、http://<servername>/FormsAuthAd (ローカルのサーバーを使用する場合は、http://localhost/FormsAuthAd) と入力し、[OK] をクリックします。
  5. [ソリューション エクスプローラ] の [参照設定] ノードを右クリックし、[参照の追加] をクリックします。
  6. [参照の追加] ダイアログ ボックスの [.NET] タブで、[System.DirectoryServices.dll]、[選択] の順にクリックし、[OK] をクリックします。

認証のコードを記述する

次の手順を実行して、LdapAuthentication.vb という名前のクラス ファイルを新規に作成します。
  1. [ソリューション エクスプローラ] で、プロジェクトのノードを右クリックし、[追加] をポイントし、[新しい項目の追加] をクリックします。
  2. [テンプレート] の [クラス] をクリックします。
  3. [ファイル名] ボックスに、LdapAuthentication.vb と入力し、[開く] をクリックします。
  4. LdapAuthentication.vb ファイルの既存のコードを、次のコードで置き換えます。
    Imports SystemImports System.TextImports System.CollectionsImports System.DirectoryServicesNamespace FormsAuth    Public Class LdapAuthentication        Dim _path As String        Dim _filterAttribute As String        Public Sub New(ByVal path As String)            _path = path        End Sub        Public Function IsAuthenticated(ByVal domain As String, ByVal username As String, ByVal pwd As String) As Boolean            Dim domainAndUsername As String = domain & "\" & username            Dim entry As DirectoryEntry = New DirectoryEntry(_path, domainAndUsername, pwd)            Try                'Bind to the native AdsObject to force authentication.			                Dim obj As Object = entry.NativeObject                Dim search As DirectorySearcher = New DirectorySearcher(entry)                search.Filter = "(SAMAccountName=" & username & ")"                search.PropertiesToLoad.Add("cn")                Dim result As SearchResult = search.FindOne()                If (result Is Nothing) Then                    Return False                End If                'Update the new path to the user in the directory.                _path = result.Path                _filterAttribute = CType(result.Properties("cn")(0), String)            Catch ex As Exception                Throw New Exception("Error authenticating user. " & ex.Message)            End Try            Return True        End Function        Public Function GetGroups() As String            Dim search As DirectorySearcher = New DirectorySearcher(_path)            search.Filter = "(cn=" & _filterAttribute & ")"            search.PropertiesToLoad.Add("memberOf")            Dim groupNames As StringBuilder = New StringBuilder()            Try                Dim result As SearchResult = search.FindOne()                Dim propertyCount As Integer = result.Properties("memberOf").Count                Dim dn As String                Dim equalsIndex, commaIndex                Dim propertyCounter As Integer                For propertyCounter = 0 To propertyCount - 1                    dn = CType(result.Properties("memberOf")(propertyCounter), String)                    equalsIndex = dn.IndexOf("=", 1)                    commaIndex = dn.IndexOf(",", 1)                    If (equalsIndex = -1) Then                        Return Nothing                    End If                    groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1))                    groupNames.Append("|")                Next            Catch ex As Exception                Throw New Exception("Error obtaining group names. " & ex.Message)            End Try            Return groupNames.ToString()        End Function    End ClassEnd Namespace					

コードの説明

認証コードは、ドメイン、ユーザー名、パスワード、および Active Directory ツリーへのパスを受け取ります。このコードでは、LDAP ディレクトリ プロバイダを使用します。
ユーザー認証
Logon.aspx ページのコードは、LdapAuthentication.IsAuthenticated メソッドを呼び出し、ユーザーから収集した資格情報を渡します。次に、ディレクトリ ツリーへのパス、ユーザー名、パスワードを使用して、DirectoryEntry オブジェクトが作成されます。ユーザー名は、"domain\username" の形式になっている必要があります。DirectoryEntry オブジェクトでは、NativeObject プロパティを取得することによって強制的に AdsObject のバインドを試行します。バインドが正常に実行された場合、DirectorySearcher オブジェクトを作成し、SAMAccountName によるフィルタリングを行って、ユーザーの CN 属性を取得します。ユーザーが認証されると、IsAuthenticated メソッドは true を返します。

: LDAP を使用して Active Directory 関連のオブジェクトにバインドする場合、TCP ポートが使用されます。System.DirectoryServices 名前空間で LDAP の使用が増加すると、利用可能なすべての TCP ポートが使用される場合があります。ユーザーの認証に使用した接続を再利用することで、TCP の負荷を低減できる場合があります。
ユーザー グループ
ユーザーが所属するグループの一覧を取得するため、このコードでは LdapAuthentication.GetGroups メソッドを呼び出します。LdapAuthentication.GetGroups メソッドは、DirectorySearcher オブジェクトを作成し、memberOf 属性に従ってフィルタリングを行うことで、そのユーザーが所属するセキュリティ グループと配布グループの一覧を取得します。このメソッドは、パイプ (|) で区切られたグループの一覧を返します。

LdapAuthentication.GetGroups メソッドが文字列を操作して切り詰めを行うことに注意します。これにより、認証 cookie に格納される文字列の長さが短くなります。文字列が切り詰められていない場合の各グループの形式を以下に示します。
CN=...,...,DC=domain,DC=com				
これは非常に長い文字列になる可能性があります。この文字列が cookie より長くなると、認証 cookie が作成されない場合があります。この文字列が cookie の長さを超える可能性がある場合は、グループの情報を ASP.NET のキャッシュ オブジェクトまたはデータベースに格納することや、グループの情報を暗号化して隠しフォーム フィールドに格納することができます。

Global.asax のコードを記述する

Global.asax ファイルのコードでは、Application_AuthenticateRequest イベント ハンドラを提供します。このイベント ハンドラは、Context.Request.Cookies コレクションから認証 cookie を取得し、cookie の暗号化を解除して、グループの一覧を取得します。この一覧は、FormsAuthenticationTicket.UserData プロパティに格納されます。各グループは、Logon.aspx ページに作成される、パイプで区切られた一覧に表示されます。

コードでは、文字列配列の文字列を解析して、GenericPrincipal オブジェクトを作成します。GenericPrincipal オブジェクトが作成されると、このオブジェクトは HttpContext.User プロパティに配置されます。
  1. ソリューション エクスプローラで、[Global.asax] を右クリックし、[コードの表示] をクリックします。
  2. 次のコードをコード ビハインド ファイル Global.asax.vb の最上部に追加します。
    Imports System.Web.SecurityImports System.Security.Principal					
  3. Application_AuthenticateRequest の既存の空のイベント ハンドラを、次のコードに置き換えます。
    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)        ' Fires upon attempting to authenticate the use        Dim cookieName As String = FormsAuthentication.FormsCookieName        Dim authCookie As HttpCookie = Context.Request.Cookies(cookieName)        If (authCookie Is Nothing) Then            'There is no authentication cookie.            Return        End If        Dim authTicket As FormsAuthenticationTicket = Nothing        Try            authTicket = FormsAuthentication.Decrypt(authCookie.Value)        Catch ex As Exception            'Write the exception to the Event Log.            Return        End Try        If (authTicket Is Nothing) Then            'Cookie failed to decrypt.            Return        End If        'When the ticket was created, the UserData property was assigned a        'pipe-delimited string of group names.        Dim groups As String() = authTicket.UserData.Split(New Char() {"|"})        'Create an Identity.        Dim id As GenericIdentity = New GenericIdentity(authTicket.Name, "LdapAuthentication")        'This principal flows throughout the request.        Dim principal As GenericPrincipal = New GenericPrincipal(id, groups)        Context.User = principal    End Sub					

Web.config ファイルを変更する

ここでは、Web.config ファイルの formsauthenticationauthorization の各要素の構成を行います。これらの変更により、認証されたユーザーのみがアプリケーションにアクセス可能となり、認証されていない要求は Logon.aspx ページにリダイレクトされます。この構成を変更することで、特定のユーザーやグループのみにアプリケーションへのアクセスを許可することができます。

Web.config ファイルの既存のコードを次のコードに置き換えます。
<?xml version="1.0" encoding="utf-8" ?><configuration>      <system.web>    <authentication mode="Forms">      <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="60" path="/" >      </forms>    </authentication>	    <authorization>	      <deny users="?" />      <allow users="*" />    </authorization>	    <identity impersonate="true" />  </system.web></configuration>				
configuration の要素 identity impersonate="true" / に注目してください。これにより ASP.NET で Microsoft インターネット インフォメーション サービス (IIS) の匿名アカウントとして構成されるアカウントの偽装が行われます。この構成を行うと、このアプリケーションに対するすべての要求は、構成済みのアカウントのセキュリティ コンテキストで実行されます。ユーザーは、Active Directory で認証されるための資格情報を提供しますが、Active Directory にアクセスするアカウントは、この構成済みのアカウントです。詳細については、「関連情報」を参照してください。

IIS で匿名認証を構成する

IIS で匿名認証を構成するには、次の手順を実行します。
  1. インターネット インフォメーション サービス (IIS) マネージャのコンソールで、"FormsAuthAd" の仮想ディレクトリを右クリックします。
  2. [プロパティ] をクリックし、[ディレクトリ セキュリティ] タブをクリックします。
  3. [認証とアクセス制御] または [匿名アクセスおよび認証コントロール] の下の [編集] をクリックします。
  4. [匿名アクセスを有効にする] または [匿名アクセス] チェック ボックスをオンにします。
  5. アプリケーションに対する匿名アカウントを、Active Directory に対するアクセス許可を持つアカウントに設定します。
  6. [IIS によるパスワードの管理を許可する] チェック ボックスをオフにします (IIS 5 の場合)。
デフォルトの IUSR_computername アカウントには、Active Directory に対するアクセス許可はありません。

Logon.aspx ページを作成する

次の手順を実行して、Logon.aspx という名前の ASP.NET Web フォームを新規作成します。
  1. ソリューション エクスプローラで、プロジェクトのノードを右クリックし、[追加] をポイントして、[Web フォームの追加] をクリックします。
  2. [ファイル名] ボックスに、Logon.aspx と入力し、[開く] をクリックします。
  3. ソリューション エクスプローラで、[Logon.aspx] を右クリックし、[デザイナの表示] をクリックします。
  4. デザイナで [HTML] タブをクリックします。
  5. 既存のコードを次のコードに置き換えます。
    <%@ Page language="vb" AutoEventWireup="true" %><%@ Import Namespace="FormsAuthAd.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">sub Login_Click(sender as object,e as EventArgs)  Dim adPath as String = "LDAP://DC=..,DC=.." 'Path to your LDAP directory server  Dim adAuth as LdapAuthentication = new LdapAuthentication(adPath)  try    if(true = adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) then      Dim groups as string = adAuth.GetGroups()      'Create the ticket, and add the groups.      Dim isCookiePersistent as boolean = chkPersist.Checked      Dim authTicket as FormsAuthenticationTicket = new FormsAuthenticationTicket(1, _           txtUsername.Text,DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups)	      'Encrypt the ticket.      Dim encryptedTicket as String = FormsAuthentication.Encrypt(authTicket)		      'Create a cookie, and then add the encrypted ticket to the cookie as data.      Dim authCookie as HttpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)      if(isCookiePersistent = true) then		authCookie.Expires = authTicket.Expiration      end if				      '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."    end if   catch ex as Exception    errorLabel.Text = "Error authenticating. " & ex.Message  end tryend sub</script>					
  6. Logon.aspx ページのパスを変更して、LDAP ディレクトリ サーバーを指定します。
Logon.aspx ページは、ユーザーから情報を収集し、LdapAuthentication クラスのメソッドを呼び出すページです。このコードは、ユーザーの認証を行い、グループの一覧を取得した後、次の順序で処理を行います。
  • FormsAuthenticationTicket オブジェクトを作成します。
  • チケットを暗号化します。
  • 暗号化したチケットを cookie に追加します。
  • その cookie を HttpResponse.Cookies コレクションに追加します。
  • 最初に要求された URL に要求をリダイレクトします。

WebForm1.aspx ページを変更する

WebForm1.aspx ページは、最初に要求されるページです。ユーザーがこのページを要求すると、その要求は Logon.aspx ページにリダイレクトされます。この要求が認証されると、その要求は WebForm1.aspx ページにリダイレクトされます。
  1. ソリューション エクスプローラで、[WebForm1.aspx] を右クリックし、[デザイナの表示] をクリックします。
  2. デザイナで [HTML] タブをクリックします。
  3. 既存のコードを次のコードで置き換えます。
    <%@ Page language="vb" 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">sub Page_Load(sender as object, e as EventArgs)  lblName.Text = "Hello " + Context.User.Identity.Name & "."  lblAuthType.Text = "You were authenticated using " &   Context.User.Identity.AuthenticationType & "."end sub</script>					
  4. すべてのファイルを保存して、プロジェクトをコンパイルします。
  5. WebForm1.aspx ページを要求します。要求は Logon.aspx にリダイレクトされます。
  6. ログオン資格情報を入力して、[Login] をクリックします。WebForm1.aspx にリダイレクトされると、ユーザー名が表示され、LdapAuthentication が Context.User.AuthenticationType プロパティに対応する認証の種類になります。
: マイクロソフトでは、フォーム認証を使用する場合は SSL (Secure Sockets Layer) の暗号化を使用することを推奨します。これは、このアプリケーションに SSL の暗号化を適用することで、ユーザーを識別するための基礎となる認証 cookie や送信されるその他の重要な情報が危険にさらされることを防止するためです。

関連情報
関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
306590 ASP.NET のセキュリティの概要
317012 ASP.NET のプロセス ID と要求 ID
306238 Visual Basic .NET を使用して、ASP.NET アプリケーションでフォーム ベースの認証にロール ベースのセキュリティを実装する方法
313091 Visual Basic .NET を使用してフォーム認証用のキーを作成する方法
313116 [PRB] フォーム認証要求が loginUrl ページにリダイレクトされない
プロパティ

文書番号:326340 - 最終更新日: 09/27/2006 06:31:34 - リビジョン: 4.3

Microsoft ASP.NET 1.0, Microsoft Visual Basic .NET 2002 Standard Edition, Microsoft ASP.NET 1.1, Microsoft Visual Basic .NET 2003 Standard Edition

  • kbconfig kbcookie kbhowtomaster kbsecurity kbwebforms KB326340
フィードバック