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

文書翻訳 文書翻訳
文書番号: 316748 - 対象製品
この記事は、以前は次の ID で公開されていました: JP316748
すべて展開する | すべて折りたたむ

目次

概要

この資料は、Lightweight Directory Access Protocol (LDAP) を使用してユーザーが Active Directory に対して認証を受けられるように、ASP.NET アプリケーションでフォーム認証を使用する方法の手順を示したものです。ユーザーが認証されてリダイレクトされた後は、Global.asax ファイルの Application_AuthenticateRequest メソッドを使用して、要求全体にわたって使用される GenericPrincipal オブジェクトを HttpContext.User プロパティに格納することができます。

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

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

認証のコードを記述する

次の手順に従って、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 オブジェクトが作成されます。ユーザー名は、"ドメイン\ユーザー名" の形式になっている必要があります。次に、NativeObject プロパティを取得することで、DirectoryEntry オブジェクトによって強制的に AdsObject バインディングが試行されます。これが成功すれば、DirectorySearcher オブジェクトを作成し、SAMAccountName によるフィルタリングを行って、ユーザーの CN 属性を取得します。ユーザーが認証されると、IsAuthenticated メソッドは true を返します。

ユーザーが所属するグループの一覧を取得するため、このコードでは LdapAuthentication.GetGroups メソッドを呼び出します。LdapAuthentication.GetGroups メソッドは、DirectorySearcher オブジェクトを作成し、memberOf 属性に従ってフィルタリングを行うことで、そのユーザーが所属するセキュリティと配布グループの一覧を取得します。このメソッドは、縦線 (|) で区切られたグループの一覧を返します。

LdapAuthentication.GetGroups メソッドが文字列を操作して切り詰めを行うことに注意してください。これにより、認証 cookie に格納される文字列の長さが短くなります。文字列を切り詰めない場合、各グループの形式は次のようになります。
CN=...,...,DC=domain,DC=com
これは非常に長い文字列になる可能性があります。この文字列の長さが cookie の長さよりも大きくなると、認証 cookie が作成されない場合があります。この文字列が cookie の長さを超える可能性がある場合は、グループの情報を HttpSession 変数に格納するか、グループの情報を暗号化して隠しフォーム フィールドに格納することもできます。

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.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 ファイルの <forms>、<authentication>、<authorization> の各要素の構成を行います。これらの変更により、認証されたユーザーだけがアプリケーションにアクセス可能となり、認証されていない要求は 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" /> に注目してください。Active Directory にアクセスする際、デフォルトの ASPNET アカウント以外のアカウントを偽装しなければならない場合があります。また、Microsoft Internet Information Services (IIS) で、匿名の認証が選択されていない場合もあります。詳細については、「関連情報 」を参照してください。

Logon.aspx ページを作成する

次の手順に従って、Logon.aspx という名前の ASP.NET Web フォームを新規に作成します。
  1. ソリューション エクスプローラで、プロジェクトのノードを右クリックし、[追加] をポイントして、[Web フォームの追加] をクリックします。
  2. [ファイル名] ボックスに Logon.aspx と入力して、[開く] をクリックします。
  3. ソリューション エクスプローラで、[Logon.aspx] を右クリックして、[デザイナの表示] をクリックします。
  4. デザイナで [HTML] タブをクリックします。
  5. 既存のコードを次のコードで置き換えます。
    <%@ 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://DC=..,DC=.."; //Path to you LDAP directory server
      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 に追加し、cookie を HttpResponse.Cookies コレクションに追加した後、最初に要求された URL に要求をリダイレクトします。

WebForm1.aspx ページを変更する

WebForm1.aspx ページは、最初に要求されるページです。ユーザーがこのページを要求すると、その要求は Logon.aspx ページにリダイレクトされます。要求の認証が行われると、その要求は WebForm1.aspx ページにリダイレクトされます。
  1. ソリューション エクスプローラで、[WebForm1.aspx] を右クリックして、[デザイナの表示] をクリックします。
  2. デザイナで [HTML] タブをクリックします。
  3. 既存のコードを次のコードで置き換えます。
    <%@ 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. ログオン資格情報を入力して、[ Login ] をクリックします。WebForm1.aspx にリダイレクトされると、ユーザー名が表示され、LdapAuthentication が Context.User.AuthenticationType プロパティに対応する認証の種類になっていることに注意してください。
: マイクロソフトでは、フォーム認証を使用する際には、Secure Sockets Layer (SSL) の暗号化を使用することを推奨しています。これは、このアプリケーションに SSL の暗号化を適用することで、ユーザーを識別するための基礎となる認証 cookie や送信されるその他の重要な情報が危険にさらされることを防止するためです。

関連情報

関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
306590 INFO: ASP.NET Security Overview
306590 [INFO] ASP.NET のセキュリティについて
317012 INFO: Process and Request Identity in ASP.NET
311495 HOW TO: Implement Role-Based Security with Forms-Based Authentication in Your ASP.NET Application by Using C# .NET
311495 [HOW TO] C# .NET を使用して、ASP.NET アプリケーションにフォーム ベースの認証とロール ベースのセキュリティを実装する方法
313091 HOW TO: Create Keys by Using Visual Basic .NET for Use in Forms Authentication
313116 PRB: Forms Authentication Requests Are Not Directed to loginUrl Page

プロパティ

文書番号: 316748 - 最終更新日: 2003年9月8日 - リビジョン: 4.2
この資料は以下の製品について記述したものです。
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft ASP.NET 1.1
キーワード:?
kbconfig kbgrpdsasp kbhowtomaster kbsecurity kbwebforms KB316748
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com