ユーザー ベースの承認 (VB)

作成者: Scott Mitchell

注意

この記事が作成されて以来、ASP.NET メンバーシップ プロバイダーは ASP.NET Identity に置き換えられました。 この記事の執筆時点で取り上げられたメンバーシップ プロバイダーではなく 、ASP.NET ID プラットフォームを使用するようにアプリを更新することを強くお勧めします。 ASP.NET ID には、ASP.NET メンバーシップ システムに比して、次のような多くの利点があります。

  • パフォーマンスの向上
  • 拡張性とテスト性の向上
  • OAuth、OpenID Connect、および 2 要素認証のサポート
  • クレームベースの ID のサポート
  • ASP.Net Core との相互運用性の向上

コードのダウンロード または PDF のダウンロード

このチュートリアルでは、さまざまな手法を使用してページへのアクセスを制限し、ページ レベルの機能を制限する方法について説明します。

はじめに

ユーザー アカウントを提供するほとんどの Web アプリケーションでは、特定の訪問者がサイト内の特定のページにアクセスすることを一部制限します。 たとえば、ほとんどのオンライン メッセージボード サイトでは、匿名と認証済みのすべてのユーザーがメッセージボードの投稿を表示できますが、認証されたユーザーのみが Web ページにアクセスして新しい投稿を作成できます。 また、特定のユーザー (または特定のユーザーのセット) のみがアクセスできる管理ページが存在する場合があります。 さらに、ページ レベルの機能は、ユーザーごとに異なる場合があります。 投稿の一覧を表示すると、認証されたユーザーは各投稿を評価するためのインターフェイスが表示されますが、このインターフェイスは匿名の訪問者には使用できません。

ASP.NET を使用すると、ユーザーベースの承認規則を簡単に定義できます。 のマークアップ Web.configを少しだけ使用すると、特定の Web ページまたはディレクトリ全体をロックダウンして、指定したユーザーのサブセットのみがアクセスできるようにすることができます。 ページ レベルの機能は、プログラムおよび宣言型の手段を使用して、現在ログインしているユーザーに基づいてオンとオフを切り替えることができます。

このチュートリアルでは、さまざまな手法を使用してページへのアクセスを制限し、ページ レベルの機能を制限する方法について説明します。 それでは作業を始めましょう。

URL 承認ワークフローの外観

フォーム認証の概要チュートリアルで説明したように、ASP.NET ランタイムが ASP.NET リソースの要求を処理すると、要求はライフサイクル中に多数のイベントを発生させます。 HTTP モジュール は、要求ライフサイクル内の特定のイベントに応答してコードが実行されるマネージド クラスです。 ASP.NET には、バックグラウンドで重要なタスクを実行する多数の HTTP モジュールが付属しています。

このような HTTP モジュールの 1 つは です FormsAuthenticationModule。 前のチュートリアルで説明したように、 の FormsAuthenticationModule 主な機能は、現在の要求の ID を決定することです。 これは、フォーム認証チケット (Cookie 内にあるか、URL 内に埋め込まれている) を検査することによって実現されます。 この識別は、イベント中にAuthenticateRequest行われます。

もう 1 つの重要な HTTP モジュールはUrlAuthorizationModule、 イベントに応答してAuthorizeRequest発生する です (イベントの後にAuthenticateRequest発生します)。 では UrlAuthorizationModule 、 の Web.config 構成マークアップを調べて、現在の ID に、指定したページにアクセスする権限があるかどうかを判断します。 このプロセスは URL 承認と呼ばれます。

手順 1 で URL 承認規則の構文を調べますが、まず、要求が承認されているかどうかに応じて、 UrlAuthorizationModule が何を行うかを見てみましょう。 によって UrlAuthorizationModule 要求が承認されると判断された場合、要求は何も行われないため、要求はそのライフサイクルを通じて続行されます。 ただし、要求が承認されていない場合、 はライフサイクルをUrlAuthorizationModule中止し、HTTP 401 Unauthorized 状態を返すようにオブジェクトに指示Responseします。 フォーム認証を使用する場合 FormsAuthenticationModule 、HTTP 401 状態が検出されると HTTP 401 状態が変更され、HTTP 302 ログイン ページにリダイレクトされるため、この HTTP 401 状態はクライアントに返されません。

図 1 は、承認されていない要求が到着した場合の、ASP.NET パイプライン、 FormsAuthenticationModule、 の UrlAuthorizationModule ワークフローを示しています。 特に、図 1 は、 の匿名訪問者 ProtectedPage.aspxによる要求を示しています。これは、匿名ユーザーへのアクセスを拒否するページです。 訪問者は匿名であるため、 は UrlAuthorizationModule 要求を中止し、HTTP 401 Unauthorized 状態を返します。 FormsAuthenticationModule次に、 は 401 状態をログイン ページへの 302 リダイレクトに変換します。 ユーザーがログイン ページを介して認証されると、 に ProtectedPage.aspxリダイレクトされます。 今回 は、 FormsAuthenticationModule 認証チケットに基づいてユーザーを識別します。 訪問者が認証されたので UrlAuthorizationModule 、 はページへのアクセスを許可します。

フォーム認証と URL 承認ワークフロー

図 1: フォーム認証と URL 承認ワークフロー (フルサイズの画像を表示する場合はクリックします)

図 1 は、匿名ユーザーが匿名ユーザーが使用できないリソースにアクセスしようとしたときに発生する相互作用を示しています。 このような場合、匿名の訪問者はログイン ページにリダイレクトされ、クエリ文字列で指定されたアクセスを試みたページが表示されます。 ユーザーが正常にログオンすると、最初に表示しようとしていたリソースに自動的にリダイレクトされます。

承認されていない要求が匿名ユーザーによって行われた場合、このワークフローは簡単で、訪問者は何が起こったのか、その理由を簡単に理解できます。 FormsAuthenticationModuleただし、 は、認証されたユーザーによって要求が行われた場合でも、承認されていないユーザーをログイン ページにリダイレクトします。 これにより、認証されたユーザーが権限のないページにアクセスしようとすると、ユーザー エクスペリエンスが混乱する可能性があります。

Web サイトの URL 承認規則が構成され、ASP.NET ページ OnlyTito.aspx に Tito のみがアクセス可能であるとします。 次に、Sam がサイトにアクセスし、ログオンし、 にアクセス OnlyTito.aspxしようとするとします。 は UrlAuthorizationModule 要求ライフサイクルを停止し、HTTP 401 Unauthorized 状態を返します。これにより が FormsAuthenticationModule 検出され、Sam がログイン ページにリダイレクトされます。 しかし、Sam は既にログインしているので、なぜログイン ページに送り返されたのか疑問に思うかもしれません。 何らかの理由でログイン資格情報が失われたか、無効な資格情報を入力した可能性があります。 Sam がログイン ページから資格情報を再入力すると、ログオン (再び) され、 に OnlyTito.aspxリダイレクトされます。 は UrlAuthorizationModule 、Sam がこのページにアクセスできないことを検出し、ログイン ページに戻ります。

図 2 は、この混乱を招くワークフローを示しています。

既定のワークフローは混乱を招く可能性があります

図 2: 既定のワークフローが混乱を招く可能性がある (クリックするとフルサイズの画像が表示されます)

図 2 に示すワークフローは、最もコンピューターに精通した訪問者でさえもすぐに理解できます。 この混乱を防ぐ方法については、手順 2 で説明します。

注意

ASP.NET では、2 つのメカニズムを使用して、現在のユーザーが特定の Web ページにアクセスできるかどうかを判断します(URL 承認とファイル承認)。 ファイルの承認は、 によって FileAuthorizationModule実装されます。これにより、要求されたファイル ACL を参照して権限が決定されます。 ファイル承認は、WINDOWS アカウントに適用されるアクセス許可であるため、Windows 認証で最も一般的に使用されます。 フォーム認証を使用する場合、サイトにアクセスするユーザーに関係なく、すべてのオペレーティング システム レベルとファイル システム レベルの要求が同じ Windows アカウントによって実行されます。 このチュートリアル シリーズではフォーム認証に焦点を当てているため、ファイルの承認については説明しません。

URL 承認のスコープ

UrlAuthorizationModuleは、ASP.NET ランタイムの一部であるマネージド コードです。 Microsoft の インターネット インフォメーション サービス (IIS) Web サーバーのバージョン 7 より前は、IIS の HTTP パイプラインと ASP.NET ランタイムのパイプラインの間に明確な障壁がありました。 つまり、IIS 6 以前では ASP です。NET は UrlAuthorizationModule 、要求が IIS から ASP.NET ランタイムに委任された場合にのみ実行されます。 既定では、IIS は HTML ページや CSS、JavaScript、イメージ ファイルなどの静的コンテンツ自体を処理し、、、または .ashx の拡張子.aspx.asmxを持つページが要求された場合にのみ、ASP.NET ランタイムに要求を送信します。

ただし、IIS 7 では、統合された IIS パイプラインと ASP.NET パイプラインを使用できます。 いくつかの構成設定を使用すると、すべての要求に対して をUrlAuthorizationModule呼び出すように IIS 7 を設定できます。つまり、任意の種類のファイルに対して URL 承認規則を定義できます。 さらに、IIS 7 には独自の URL 承認エンジンが含まれています。 ASP.NET 統合と IIS 7 のネイティブ URL 承認機能の詳細については、「 IIS7 URL 承認について」を参照してください。 ASP.NET と IIS 7 の統合の詳細については、Shahram Khosravi の書籍である Professional IIS 7 と ASP.NET Integrated Programming (ISBN: 978-0470152539) のコピーを入手してください。

簡単に言うと、IIS 7 より前のバージョンでは、URL 承認規則は、ASP.NET ランタイムによって処理されるリソースにのみ適用されます。 ただし、IIS 7 では、IIS のネイティブ URL 承認機能を使用することも、ASP を統合することもできます。NET は UrlAuthorizationModule IIS の HTTP パイプラインに入り、この機能をすべての要求に拡張します。

注意

ASP の方法には、微妙でありながら重要な違いがいくつかあります。 UrlAuthorizationModule NET と IIS 7 の URL 承認機能は、承認規則を処理します。 このチュートリアルでは、IIS 7 の URL 承認機能や、 と比較した承認規則の解析方法の UrlAuthorizationModule違いについては説明しません。 これらのトピックの詳細については、MSDN または www.iis.net の IIS 7 ドキュメントを参照してください。

手順 1: で URL 承認規則を定義するWeb.config

UrlAuthorizationModule 、アプリケーションの構成で定義されている URL 承認規則に基づいて、特定の ID に対して要求されたリソースへのアクセスを許可または拒否するかどうかを決定します。 承認規則は、 要素と <authorization> 子要素<allow><deny>形式でスペルが指定されます。 各 <allow> 要素と <deny> 子要素では、次を指定できます。

  • 特定のユーザー
  • ユーザーのコンマ区切りの一覧
  • 疑問符 (?) で示されているすべての匿名ユーザー
  • アスタリスク (*) で示されるすべてのユーザー

次のマークアップは、URL 承認規則を使用して、ユーザー Tito と Scott を許可し、他のすべてのユーザーを拒否する方法を示しています。

<authorization>
 <allow users="Tito, Scott" />
 <deny users="*" />
</authorization>

要素は <allow> 、許可されるユーザー (Tito と Scott) を定義し <deny> 、要素 はすべての ユーザーが拒否されることを指示します。

注意

要素と <deny> 要素では<allow>、ロールの承認規則を指定することもできます。 今後のチュートリアルでは、ロールベースの承認について調べます。

次の設定では、Sam 以外のユーザー (匿名の訪問者を含む) へのアクセスが許可されます。

<authorization>
 <deny users="Sam" />
</authorization>

認証されたユーザーのみを許可するには、すべての匿名ユーザーへのアクセスを拒否する次の構成を使用します。

<authorization>
 <deny users="?" />
</authorization>

承認規則は、 の 要素内 <system.web>Web.config 定義され、Web アプリケーション内のすべての ASP.NET リソースに適用されます。 多くの場合、アプリケーションにはセクションごとに異なる承認規則があります。 たとえば、e コマース サイトでは、すべての訪問者が製品を熟読したり、製品のレビューを見たり、カタログを検索したりできます。 ただし、認証済みのユーザーのみがチェックアウトまたはページに到達して出荷履歴を管理できます。 また、サイト管理者など、一部のユーザーのみがサイトにアクセスできる場合があります。

ASP.NET を使用すると、サイト内のファイルやフォルダーごとに異なる承認規則を簡単に定義できます。 ルート フォルダーのファイルで指定された承認規則は、 Web.config サイト内のすべての ASP.NET リソースに適用されます。 ただし、これらの既定の承認設定は、セクションを含む を追加Web.config<authorization>することで、特定のフォルダーに対してオーバーライドできます。

認証されたユーザーのみがフォルダー内の ASP.NET ページにアクセスできるように、Web サイトを Membership 更新しましょう。 これを実現するには、フォルダーにファイルを Web.config 追加し、匿名ユーザーを Membership 拒否するように承認設定を設定する必要があります。 ソリューション エクスプローラー内のフォルダーをMembership右クリックし、コンテキスト メニューから [新しい項目の追加] メニューを選択し、 という名前Web.configの新しい Web 構成ファイルを追加します。

メンバーシップ フォルダーにWeb.config ファイルを追加する

図 3: フォルダーにファイルをMembership追加Web.configする (クリックするとフルサイズの画像が表示されます)

この時点で、プロジェクトには 2 つの Web.config ファイル (1 つはルート ディレクトリに、もう 1 つはフォルダー内) が Membership 含まれている必要があります。

アプリケーションに2つのWeb.configファイルが含まれるようになりました

図 4: アプリケーションに 2 つの Web.config ファイルが含まれている必要がある (クリックするとフルサイズの画像が表示されます)

フォルダー内の構成ファイルを Membership 更新して、匿名ユーザーへのアクセスを禁止します。

<?xml version="1.0"?>
<configuration>
 <system.web>
 <authorization>
 <deny users="?" />
 </authorization>
 </system.web>
</configuration>

これですべて完了です。

この変更をテストするには、ブラウザーのホームページにアクセスし、ログアウトしていることを確認します。ASP.NET アプリケーションの既定の動作は、すべての訪問者を許可するため、ルート ディレクトリの Web.config ファイルに対して承認の変更を行わなかったため、匿名の訪問者としてルート ディレクトリ内のファイルにアクセスできます。

左側の列にある [ユーザー アカウントの作成] リンクをクリックします。 これにより、 に ~/Membership/CreatingUserAccounts.aspx連れて行きます。 フォルダー内MembershipWeb.configファイルでは匿名アクセスを禁止する承認規則が定義されているため、 はUrlAuthorizationModule要求を中止し、HTTP 401 Unauthorized 状態を返します。 は FormsAuthenticationModule 、これを 302 リダイレクト状態に変更し、ログイン ページに送信します。 アクセスしようとしたページ (CreatingUserAccounts.aspx) は、querystring パラメーターを使用してログイン ページに ReturnUrl 渡されることに注意してください。

URL 承認規則では匿名アクセスが禁止されているため、ログイン ページにリダイレクトされます

図 5: URL 承認規則では匿名アクセスが禁止されているため、ログイン ページにリダイレクトされます (フルサイズの画像を表示する をクリックします)

正常にログインすると、ページに CreatingUserAccounts.aspx リダイレクトされます。 今回は、 UrlAuthorizationModule 匿名ではなくなったため、 によってページへのアクセスが許可されます。

特定の場所への URL 承認規則の適用

Web.configセクションで<system.web>定義されている承認設定は、そのディレクトリとそのサブディレクトリ内のすべての ASP.NET リソースに適用されます (それ以外の場合は別Web.configのファイルによってオーバーライドされるまで)。 ただし、1 つまたは 2 つの特定のページを除き、特定のディレクトリ内のすべての ASP.NET リソースに特定の承認構成が必要な場合もあります。 これを実現するには、 に Web.config要素を<location>追加し、承認規則が異なるファイルを指し示し、その中で一意の承認規則を定義します。

要素を <location> 使用して特定のリソースの構成設定をオーバーライドする方法を説明するために、Tito のみが にアクセス CreatingUserAccounts.aspxできるように承認設定をカスタマイズしましょう。 これを実現するには、フォルダーのWeb.configファイルに 要素をMembership追加<location>し、次のようにマークアップを更新します。

<?xml version="1.0"?>
<configuration>
 <system.web>
 <authorization>
 <deny users="?" />
 </authorization>
 </system.web>

 <location path="CreatingUserAccounts.aspx">
 <system.web>
 <authorization>
 <allow users="Tito" />
 <deny users="*" />
 </authorization>
 </system.web>
 </location>
</configuration>

<system.web> 要素は<authorization>、フォルダーとそのサブフォルダー内の ASP.NET リソースの既定の URL 承認規則をMembership定義します。 要素を <location> 使用すると、特定のリソースに対してこれらのルールをオーバーライドできます。 上記のマークアップでは、 要素は <location> ページを CreatingUserAccounts.aspx 参照し、 などの承認規則を指定して Tito を許可しますが、他のすべてのユーザーを拒否します。

この承認の変更をテストするには、まず、匿名ユーザーとして Web サイトにアクセスします。 などのUserBasedAuthorization.aspxUrlAuthorizationModuleフォルダー内の任意のMembershipページにアクセスしようとすると、 によって要求が拒否され、ログイン ページにリダイレクトされます。 Scott のようにログインした後は、 を除くCreatingUserAccounts.aspxフォルダー内の任意のページにMembershipアクセスできます。 Tito 以外のユーザーとしてログオンしているユーザーとしてアクセス CreatingUserAccounts.aspx しようとすると、不正アクセスが試行され、ログイン ページにリダイレクトされます。

注意

要素は <location> 、構成 <system.web> の 要素の外部に表示する必要があります。 承認設定をオーバーライドするリソースごとに個別 <location> の要素を使用する必要があります。

承認規則をUrlAuthorizationModule使用してアクセスを許可または拒否する方法を見る

では UrlAuthorizationModule 、URL 承認規則を一度に 1 つずつ分析し、最初の URL から始めて、その方法で作業することで、特定の URL に対して特定の ID を承認するかどうかを決定します。 一致が見つかるとすぐに、 要素または <deny> 要素で<allow>一致が見つかったかどうかに応じて、ユーザーはアクセスを許可または拒否されます。 一致するものが見つからない場合、ユーザーにはアクセス権が付与されます。 そのため、アクセスを制限する場合は、URL 承認構成の最後の要素として 要素を使用 <deny> することが不可欠です。 を省略した場合、<deny>要素を使用すると、すべてのユーザーにアクセス権が付与されます。

によって使用される UrlAuthorizationModule プロセスをより深く理解して機関を決定するには、この手順で前に見た URL 承認規則の例を考えてみましょう。 最初のルールは、 <allow> Tito と Scott へのアクセスを許可する要素です。 2 つ目のルールは、 <deny> すべてのユーザーへのアクセスを拒否する要素です。 匿名ユーザーがアクセスした場合、 は UrlAuthorizationModule まず、匿名の Scott または Tito のどちらかを求めることから始まります。 答えは明らかにいいえなので、2番目のルールに進みます。 全員のセットで匿名ですか? ここでの回答は [はい] であるため、 <deny> ルールは有効になり、訪問者はログイン ページにリダイレクトされます。 同様に、Jisun が訪問している場合は、 UrlAuthorizationModule まず、Jisun は Scott か Tito か尋ねることから始まります。 彼女はないので、2番目の UrlAuthorizationModule 質問に進みます,ジサンはみんなのセットですか? 彼女もアクセスを拒否されています。 最後に、ティトが訪問した場合、によってもたらされる最初の UrlAuthorizationModule 質問は肯定的な答えであるため、Titoにはアクセス権が付与されます。

では UrlAuthorizationModule 、上から下に向けて承認規則を処理し、一致で停止するので、より具体的でないルールの前に、より具体的なルールを作成することが重要です。 つまり、Jisun と匿名ユーザーを禁止し、他のすべての認証されたユーザーを許可する承認規則を定義するには、最も具体的なルール (Jisun に影響を与えるルール) から始めて、他のすべての認証済みユーザーを許可するものの、すべての匿名ユーザーを拒否する規則に進みます。 次の URL 承認規則では、最初に Jisun を拒否してから匿名ユーザーを拒否することで、このポリシーを実装します。 これらの <deny> ステートメントはどちらも一致しないため、Jisun 以外の認証済みユーザーにはアクセス権が付与されます。

<authorization>
 <deny users="Jisun" />
 <deny users="?" />
</authorization>

手順 2: 承認されていない、認証されたユーザーのワークフローを修正する

このチュートリアルの「URL 承認ワークフローの確認」セクションで前述したように、承認されていない要求がトランスパイルされると、要求が中止され、 UrlAuthorizationModule HTTP 401 Unauthorized 状態が返されます。 この 401 状態は、 によって FormsAuthenticationModule ログイン ページにユーザーを送信する 302 リダイレクト状態に変更されます。 このワークフローは、ユーザーが認証された場合でも、承認されていない要求で発生します。

認証されたユーザーをログイン ページに戻すと、既にシステムにログインしているため、ユーザーが混乱する可能性があります。 少しの作業により、承認されていない要求を行った認証済みユーザーを、制限付きページへのアクセスを試みたことを説明するページにリダイレクトすることで、このワークフローを改善できます。

最初に、 という名前 UnauthorizedAccess.aspxの Web アプリケーションのルート フォルダーに新しい ASP.NET ページを作成します。このページをマスター ページに関連付けるのを Site.master 忘れないでください。 このページを作成したら、ContentPlaceHolder を参照する Content コントロールを LoginContent 削除して、マスター ページの既定のコンテンツが表示されるようにします。 次に、ユーザーが保護されたリソースにアクセスしようとしたという状況を説明するメッセージを追加します。 このようなメッセージを追加すると、 UnauthorizedAccess.aspx ページの宣言型マークアップは次のようになります。

<%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false"
CodeFile="UnauthorizedAccess.aspx.cs" Inherits="UnauthorizedAccess"
Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent"
Runat="Server">
 <h2>Unauthorized Access</h2>
 <p>
 You have attempted to access a page that you are not authorized to view.
 </p>
 <p>
 If you have any questions, please contact the site administrator.
 </p>
</asp:Content>

認証されたユーザーが承認されていない要求を実行した場合、ログイン ページではなくページに送信されるように、ワークフローを変更する UnauthorizedAccess.aspx 必要があります。 承認されていない要求をログイン ページにリダイレクトするロジックは、 クラスのプライベート メソッド内に埋もれているため FormsAuthenticationModule 、この動作をカスタマイズすることはできません。 ただし、実行できることは、必要に応じてユーザーを にリダイレクトする独自のロジックをログイン ページに UnauthorizedAccess.aspx追加することです。

FormsAuthenticationModuleが未承認の訪問者をログイン ページにリダイレクトすると、要求された未承認の URL が という名前ReturnUrlのクエリ文字列に追加されます。 たとえば、承認されていないユーザーが にアクセス OnlyTito.aspxしようとすると、 FormsAuthenticationModule によって に Login.aspx?ReturnUrl=OnlyTito.aspxリダイレクトされます。 したがって、パラメーターを含む ReturnUrl クエリ文字列を持つ認証されたユーザーがログイン ページに到達した場合、この認証されていないユーザーがページにアクセスしようとしただけで、表示が許可されていないことがわかっています。 このような場合は、彼女を に UnauthorizedAccess.aspxリダイレクトします。

これを実現するには、ログイン ページのイベント ハンドラーに次の Page_Load コードを追加します。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 If Not Page.IsPostBack Then
 If Request.IsAuthenticated AndAlso Not String.IsNullOrEmpty(Request.QueryString("ReturnUrl")) Then
 ' This is an unauthorized, authenticated request...
 Response.Redirect("~/UnauthorizedAccess.aspx")
 End If
 End If
End Sub

上記のコードは、認証された承認されていないユーザーをページに UnauthorizedAccess.aspx リダイレクトします。 このロジックの動作を確認するには、匿名の訪問者としてサイトにアクセスし、左側の列にある [Createing User Accounts]\(ユーザー アカウントの作成\) リンクをクリックします。 これにより、ページが ~/Membership/CreatingUserAccounts.aspx 表示されます。手順 1 では、Tito へのアクセスのみを許可するように構成しました。 匿名ユーザーは禁止されているため、 FormsAuthenticationModule ログイン ページにリダイレクトされます。

この時点で、私たちは匿名なので Request.IsAuthenticated 、 が False 返され、 に UnauthorizedAccess.aspxリダイレクトされません。 代わりに、ログイン ページが表示されます。 Bruce など、Tito 以外のユーザーとしてログインします。 適切な資格情報を入力すると、ログイン ページによって に ~/Membership/CreatingUserAccounts.aspxリダイレクトされます。 ただし、このページには Tito からのみアクセスできるため、このページを表示することは許可されておらず、すぐにログイン ページに戻ります。 ただし Request.IsAuthenticated 、今回は を返 True す (および ReturnUrl querystring パラメーターが存在する) ため、ページに UnauthorizedAccess.aspx リダイレクトされます。

認証された、未承認のユーザーが UnauthorizedAccess.aspx にリダイレクトされる

図 6: 認証され、承認されていないユーザーが に UnauthorizedAccess.aspx リダイレクトされる (フルサイズの画像を表示する をクリックします)

このカスタマイズされたワークフローは、図 2 に示されているサイクルをショートサーキットすることで、より賢明で簡単なユーザー エクスペリエンスを提供します。

手順 3: 現在ログインしているユーザーに基づいて機能を制限する

URL 承認を使用すると、粗い承認規則を簡単に指定できます。 手順 1 で説明したように、URL 承認を使用して、許可される ID と、フォルダー内の特定のページまたはすべてのページの表示が拒否される ID を簡潔に示すことができます。 ただし、特定のシナリオでは、すべてのユーザーがページにアクセスできるようにし、ページにアクセスするユーザーに基づいてページの機能を制限することができます。

認証済みの訪問者が製品をレビューできるようにする e コマース Web サイトのケースを考えてみましょう。 匿名ユーザーが製品のページにアクセスすると、製品情報だけが表示され、レビューを終了する機会は与えまれません。 ただし、認証されたユーザーが同じページにアクセスすると、レビュー インターフェイスが表示されます。 認証されたユーザーがこの製品をまだレビューしていない場合、インターフェイスによってレビューを送信できるようになります。それ以外の場合は、以前に送信されたレビューが表示されます。 このシナリオをさらに進めるために、製品ページに追加情報が表示され、eコマース会社で働くユーザー向けの拡張機能が提供される場合があります。 たとえば、製品ページには在庫が一覧表示され、従業員が訪問したときに製品の価格と説明を編集するためのオプションが含まれる場合があります。

このようなきめ細かい承認規則は、宣言的またはプログラム的に (または 2 つの組み合わせを使用して) 実装できます。 次のセクションでは、LoginView コントロールを使用してきめ細かい承認を実装する方法について説明します。 その後、プログラムによる手法について説明します。 ただし、きめ細かい承認規則の適用を見る前に、まず、アクセスするユーザーに依存する機能を持つページを作成する必要があります。

GridView 内の特定のディレクトリ内のファイルを一覧表示するページを作成しましょう。 各ファイルの名前、サイズ、およびその他の情報を一覧表示すると共に、GridView には LinkButtons の 2 つの列が含まれます。1 つは View というタイトルで、もう 1 つは Delete というタイトルです。 View LinkButton をクリックすると、選択したファイルの内容が表示されます。[LinkButton の削除] をクリックすると、ファイルが削除されます。 最初に、ビューと削除の機能をすべてのユーザーが使用できるように、このページを作成しましょう。 [LoginView コントロールの使用] セクションと [プログラムによる機能の制限] セクションでは、ページにアクセスするユーザーに基づいて、これらの機能を有効または無効にする方法について説明します。

注意

作成しようとしている ASP.NET ページでは、GridView コントロールを使用してファイルの一覧を表示します。 このチュートリアル シリーズでは、フォーム認証、承認、ユーザー アカウント、ロールに焦点を当てているため、GridView コントロールの内部動作について説明するのにあまり時間を費やしたくありません。 このチュートリアルでは、このページを設定するための具体的な手順を説明しますが、特定の選択が行われた理由や、レンダリングされた出力に対する特定のプロパティの影響の詳細については説明しません。 GridView コントロールの詳細については、「 ASP.NET 2.0 でのデータの操作」 チュートリアル シリーズを参照してください。

まず、 フォルダー内のファイルをUserBasedAuthorization.aspxMembership開き、 という名前FilesGridのページに GridView コントロールを追加します。 GridView のスマート タグで、[列の編集] リンクをクリックして [フィールド] ダイアログ ボックスを起動します。 ここから、左下隅にある [フィールドの自動生成] チェック ボックスをオフにします。 次に、左上隅から [選択] ボタン、[削除] ボタン、および 2 つの BoundField を追加します ([選択] ボタンと [削除] ボタンは、CommandField 型の下にあります)。 [選択] ボタンのSelectTextプロパティを [表示] に設定し、最初の BoundField とHeaderTextDataFieldプロパティを [名前] に設定します。 2 番目の BoundField の HeaderText プロパティを Size in Bytes に設定し、その DataField プロパティを Length に、その DataFormatString プロパティを に {0:N0} 設定し、その HtmlEncode プロパティを False に設定します。

GridView の列を構成したら、[OK] をクリックして [フィールド] ダイアログ ボックスを閉じます。 プロパティ ウィンドウから、GridView の DataKeyNames プロパティを にFullName設定します。 この時点で、GridView の宣言型マークアップは次のようになります。

<asp:GridView ID="FilesGrid" DataKeyNames="FullName" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:CommandField SelectText="View" ShowSelectButton="True"/>
 <asp:CommandField ShowDeleteButton="True" />
 <asp:BoundField DataField="Name" HeaderText="Name" />
 <asp:BoundField DataField="Length" DataFormatString="{0:N0}"
 HeaderText="Size in Bytes" HtmlEncode="False" />
 </Columns>
</asp:GridView>

GridView のマークアップを作成したら、特定のディレクトリ内のファイルを取得して GridView にバインドするコードを記述する準備ができました。 ページのイベント ハンドラーに次の Page_Load コードを追加します。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 If Not Page.IsPostBack Then
 Dim appPath As String = Request.PhysicalApplicationPath
 Dim dirInfo As New DirectoryInfo(appPath)

 Dim files() As FileInfo = dirInfo.GetFiles()

 FilesGrid.DataSource = files
 FilesGrid.DataBind()
 End If
End Sub

上記のコードでは、 クラスをDirectoryInfo使用して、アプリケーションのルート フォルダー内のファイルの一覧を取得します。 メソッドはGetFiles()、ディレクトリ内のすべてのファイルをオブジェクトのFileInfo配列として返し、GridView にバインドします。 FileInfoオブジェクトには、 などのNameLengthIsReadOnlyさまざまなプロパティがあります。 宣言型マークアップからわかるように、GridView には プロパティと Length プロパティだけがName表示されます。

注意

DirectoryInfoクラスと FileInfo クラスは、 名前空間にありますSystem.IO。 したがって、これらのクラス名の前に名前空間名を付けるか、 を使用して Imports System.IOクラス ファイルに名前空間をインポートする必要があります。

ブラウザーからこのページにアクセスしてください。 アプリケーションのルート ディレクトリに存在するファイルの一覧が表示されます。 View または Delete LinkButtons のいずれかをクリックするとポストバックが発生しますが、必要なイベント ハンドラーをまだ作成していないため、アクションは発生しません。

GridView には、Web アプリケーションのルート ディレクトリ内のファイルが一覧表示されます

図 7: GridView は、Web アプリケーションのルート ディレクトリ内のファイルを一覧表示します (フルサイズの画像を表示する をクリックします)

選択したファイルの内容を表示する手段が必要です。 Visual Studio に戻り、GridView の上にという名前 FileContents の TextBox を追加します。 そのプロパティを TextModeMultiLine 、その Columns プロパティと Rows プロパティをそれぞれ 95% と 10 に設定します。

<asp:TextBox ID="FileContents" runat="server" Rows="10"
TextMode="MultiLine" Width="95%"></asp:TextBox>

次に、GridView のイベントのイベント ハンドラーを作成し、次のSelectedIndexChangedコードを追加します。

Protected Sub FilesGrid_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles FilesGrid.SelectedIndexChanged
 ' Open the file and display it
 Dim fullFileName As String = FilesGrid.SelectedValue.ToString()
 Dim contents As String = File.ReadAllText(fullFileName)
 FileContents.Text = contents
End Sub

このコードでは、GridView の SelectedValue プロパティを使用して、選択したファイルの完全なファイル名を決定します。 内部的には、 DataKeys コレクションは を取得 SelectedValueするために参照されるため、この手順で前述したように、GridView の DataKeyNames プロパティを Name に設定する必要があります。 クラスはFile、選択したファイルの内容を文字列に読み取るために使用され、テキスト ボックスの Text プロパティにFileContents割り当てられ、選択したファイルの内容がページに表示されます。

選択したファイルの内容がテキスト ボックスに表示されます

図 8: 選択したファイルの内容がテキスト ボックスに表示される (フルサイズの画像を表示する をクリックします)

注意

HTML マークアップを含むファイルの内容を表示し、ファイルの表示または削除を試みると、エラーが HttpRequestValidationException 発生します。 これは、ポストバック時に TextBox のコンテンツが Web サーバーに送り返されるために発生します。 既定では、html マークアップなどの危険なポストバック コンテンツが検出されるたびに、ASP.NET によってエラーが発生 HttpRequestValidationException します。 このエラーが発生しないようにするには、 ディレクティブに を追加 ValidateRequest="false" して、ページの要求検証を @Page オフにします。 要求の検証の利点と、それを無効にする際に実行する必要がある予防措置の詳細については、「 要求の検証 - スクリプト攻撃の防止」を参照してください。

最後に、GridView RowDeletingのイベントに対して次のコードを含むイベント ハンドラーを追加します。

Protected Sub FilesGrid_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs)Handles FilesGrid.RowDeleting
 Dim fullFileName As String = FilesGrid.DataKeys(e.RowIndex).Value.ToString()
 FileContents.Text = String.Format("You have opted to delete {0}.", fullFileName)

 ' To actually delete the file, uncomment the following line
 ' File.Delete(fullFileName)
End Sub

このコードでは、実際にファイルを削除することなく、削除FileContentsするファイルの完全な名前を TextBox に表示するだけです。

[削除] ボタンをクリックしても、ファイルは実際には削除されません

図 9: [削除] ボタンをクリックしてもファイルが実際に削除されない (クリックするとフルサイズの画像が表示されます)

手順 1 では、匿名ユーザーがフォルダー内のページを表示できないように URL 承認規則を Membership 構成しました。 きめ細かい認証をより適切に表示するために、匿名ユーザーにページへのアクセスを UserBasedAuthorization.aspx 許可しますが、機能は制限されています。 このページを開いてすべてのユーザーがアクセスできるようにするには、 フォルダー内の ファイルに次 <location>Web.config 要素を Membership 追加します。

<location path="UserBasedAuthorization.aspx">
 <system.web>
 <authorization>
 <allow users="*" />
 </authorization>
 </system.web>
</location>

この <location> 要素を追加した後、サイトからログアウトして新しい URL 承認規則をテストします。 匿名ユーザーとして、ページへのアクセスを UserBasedAuthorization.aspx 許可する必要があります。

現在、認証されたユーザーまたは匿名ユーザーは、ページにアクセスし、ファイルを UserBasedAuthorization.aspx 表示または削除できます。 認証されたユーザーのみがファイルの内容を表示でき、Tito のみがファイルを削除できるようにしましょう。 このようなきめ細かい承認規則は、宣言的、プログラム的、または両方のメソッドの組み合わせを使用して適用できます。 宣言型のアプローチを使用して、ファイルの内容を表示できるユーザーを制限しましょう。プログラムによるアプローチを使用して、ファイルを削除できるユーザーを制限します。

LoginView コントロールの使用

過去のチュートリアルで説明したように、LoginView コントロールは、認証されたユーザーと匿名ユーザーのさまざまなインターフェイスを表示するのに役立ち、匿名ユーザーがアクセスできない機能を簡単に非表示にする方法を提供します。 匿名ユーザーはファイルを表示または削除できないため、認証されたユーザーがページに FileContents アクセスした場合にのみ TextBox を表示する必要があります。 これを実現するには、LoginView コントロールをページに追加し、 という名前を付けてLoginViewForFileContentsTextBox、TextBox の宣言型マークアップを LoginView コントロールの LoggedInTemplateに移動FileContentsします。

<asp:LoginView ID=" LoginViewForFileContentsTextBox " runat="server">
 <LoggedInTemplate>
 <p>
 <asp:TextBox ID="FileContents" runat="server" Rows="10"
 TextMode="MultiLine" Width="95%"></asp:TextBox>
 </p>
 </LoggedInTemplate>
</asp:LoginView>

LoginView のテンプレート内の Web コントロールは、分離コード クラスから直接アクセスできなくなりました。 たとえば、FilesGridGridView とRowDeletingイベント ハンドラーはSelectedIndexChanged現在、次のようなコードで FileContents TextBox コントロールを参照しています。

FileContents.Text = text

ただし、このコードは無効です。 TextBox を FileContents TextBox に LoggedInTemplate 移動すると、直接アクセスすることはできません。 代わりに、 メソッドを FindControl("controlId") 使用してプログラムでコントロールを参照する必要があります。 FilesGrid次のように TextBox を参照するようにイベント ハンドラーを更新します。

Dim FileContentsTextBox As TextBox = CType(LoginViewForFileContentsTextBox.FindControl("FileContents"),TextBox)
FileContentsTextBox.Text = text

TextBox を LoginView LoggedInTemplate に移動し、パターンを使用して FindControl("controlId") TextBox を参照するようにページのコードを更新した後、匿名ユーザーとしてページにアクセスします。 図 10 に示すように、 FileContents TextBox は表示されません。 ただし、View LinkButton は引き続き表示されます。

LoginView コントロールは、認証されたユーザーの FileContents TextBox のみをレンダリングします

図 10: LoginView コントロールは、認証されたユーザーの FileContents TextBox のみをレンダリングします (フルサイズの画像を表示する場合はクリックします)

匿名ユーザーの [表示] ボタンを非表示にする 1 つの方法は、GridView フィールドを TemplateField に変換することです。 これにより、View LinkButton の宣言型マークアップを含むテンプレートが生成されます。 次に、LoginView コントロールを TemplateField に追加し、LinkButton を LoginView の LoggedInTemplate内に配置して、匿名の訪問者から [表示] ボタンを非表示にすることができます。 これを行うには、GridView のスマート タグから [列の編集] リンクをクリックして、[フィールド] ダイアログ ボックスを起動します。 次に、左下隅にある一覧から [選択] ボタンを選択し、[このフィールドを TemplateField に変換する] リンクをクリックします。 これにより、フィールドの宣言型マークアップは次のように変更されます。

<asp:CommandField SelectText="View" ShowSelectButton="True"/>

移動先:

<asp:TemplateField ShowHeader="False">
 <ItemTemplate>
 <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
 CommandName="Select" Text="View"></asp:LinkButton>
 </ItemTemplate>
</asp:TemplateField>

この時点で、TemplateField に LoginView を追加できます。 次のマークアップでは、認証されたユーザーに対してのみ View LinkButton が表示されます。

<asp:TemplateField ShowHeader="False">
 <ItemTemplate>
 <asp:LoginView ID="LoginView1" runat="server">
 <LoggedInTemplate>
 <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
 CommandName="Select" Text="View"></asp:LinkButton>
 </LoggedInTemplate>
 </asp:LoginView>
 </ItemTemplate>
</asp:TemplateField>

図 11 に示すように、最終的な結果は、列内の [リンク ボタンの表示] が非表示になっている場合でも、[表示] 列が表示されるため、その結果は表示されません。 次のセクションでは、GridView 列全体 (LinkButton だけでなく) を非表示にする方法について説明します。

LoginView コントロールは、匿名訪問者の View LinkButtons を非表示にします

図 11: LoginView コントロールは、匿名の訪問者の LinkButtons の表示を非表示にします (フルサイズの画像を表示する 場合はクリックします)

プログラムによる機能の制限

状況によっては、宣言型の手法では機能をページに制限するには不十分です。 たとえば、特定のページ機能の可用性は、ページにアクセスするユーザーが匿名であるか認証されているかを超える条件に依存する場合があります。 このような場合、さまざまなユーザー インターフェイス要素は、プログラムによる手段によって表示または非表示にすることができます。

プログラムで機能を制限するには、次の 2 つのタスクを実行する必要があります。

  1. ページにアクセスするユーザーが機能にアクセスできるかどうかを判断し、
  2. ユーザーが問題の機能にアクセスできるかどうかに基づいて、プログラムによってユーザー インターフェイスを変更します。

これら 2 つのタスクの適用例を示すために、Tito が GridView からファイルを削除することを許可します。 最初のタスクは、ページにアクセスする Tito かどうかを判断することです。 それが決定されたら、GridView の Delete 列を非表示 (または表示) する必要があります。 GridView の列には、その Columns プロパティを使用してアクセスできます。列は、その Visible プロパティが (既定値) に True 設定されている場合にのみレンダリングされます。

データを GridView にバインドする Page_Load 前に、次のコードをイベント ハンドラーに追加します。

' Is this Tito visiting the page?
Dim userName As String = User.Identity.Name
If String.Compare(userName, "Tito", True) = 0 Then
 ' This is Tito, SHOW the Delete column
 FilesGrid.Columns(1).Visible = True
Else
 ' This is NOT Tito, HIDE the Delete column
 FilesGrid.Columns(1).Visible = False
End If

フォーム認証の概要チュートリアルで説明したように、 User.Identity.Name ID の名前が返されます。 これは、Login コントロールに入力されたユーザー名に対応します。 ページにアクセスする Tito の場合、GridView の 2 番目の列の Visible プロパティは に True設定されます。それ以外の場合は に False設定されます。 結果として、Tito 以外のユーザーが別の認証済みユーザーまたは匿名ユーザーのページにアクセスすると、Delete 列はレンダリングされません (図 12 を参照)。ただし、Tito がページにアクセスすると、Delete 列が存在します (図 13 を参照)。

Tito 以外のユーザー (Bruce など) がアクセスした場合、Delete 列はレンダリングされません

図 12: Tito 以外のユーザー (Bruce など) がアクセスした場合、[列の削除] はレンダリングされません (フルサイズの画像を表示する場合はクリックします)

Delete 列は Tito に対してレンダリングされます

図 13: [列の削除] が Tito に対してレンダリングされる (フルサイズの画像を表示する場合をクリックします)

手順 4: クラスとメソッドに承認規則を適用する

手順 3 では、匿名ユーザーがファイルの内容を表示することを禁止し、Tito 以外のすべてのユーザーがファイルを削除することを禁止しました。 これは、宣言的およびプログラム的な手法を使用して、承認されていない訪問者に関連付けられているユーザー インターフェイス要素を非表示にすることで実現されました。 この簡単な例では、ユーザー インターフェイス要素を適切に非表示にすることは簡単でしたが、同じ機能を実行するさまざまな方法があるより複雑なサイトはどうでしょうか。 その機能を承認されていないユーザーに制限する場合、該当するすべてのユーザー インターフェイス要素を非表示または無効にし忘れた場合はどうなりますか?

承認されていないユーザーが特定の機能にアクセスできないようにする簡単な方法は、そのクラスまたはメソッドを 属性で PrincipalPermission 装飾することです。 .NET ランタイムは、クラスを使用するか、そのメソッドのいずれかを実行するときに、現在のセキュリティ コンテキストに クラスを使用する権限またはメソッドを実行するアクセス許可があることを確認します。 属性は PrincipalPermission 、これらの規則を定義するためのメカニズムを提供します。

GridView の イベント ハンドラーで 属性をPrincipalPermission使用して、匿名ユーザーと RowDeleting Tito 以外のSelectedIndexChangedユーザーによる実行をそれぞれ禁止する方法を示します。 必要なのは、各関数定義の上に適切な属性を追加することです。

<PrincipalPermission(SecurityAction.Demand, Authenticated:=True)> _
Protected Sub FilesGrid_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles FilesGrid.SelectedIndexChanged
 ...
End Sub

<PrincipalPermission(SecurityAction.Demand, Name:="Tito")> _
Protected Sub FilesGrid_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles FilesGrid.RowDeleting
 ...
End Sub

イベント ハンドラーの SelectedIndexChanged 属性は、認証されたユーザーのみがイベント ハンドラーを実行できるように指定します。イベント ハンドラーの RowDeleting 属性では、実行が Tito に制限されます。

注意

属性は、クラス、メソッド、プロパティ、またはイベントに適用できます。 属性を追加する場合は、クラス、メソッド、プロパティ、またはイベント宣言ステートメントの一部である必要があります。 Visual Basic ではステートメント区切り記号として改行が使用されるため、属性は宣言と同じ行に表示するか、行連結文字 (アンダースコア) を使用してその真上に表示する必要があります。 上記のコード スニペットでは、行連結文字を使用して、ある行に属性を配置し、メソッド宣言を別の行に配置します。

何らかの方法で、Tito 以外のユーザーがイベント ハンドラーを実行 RowDeleting しようとした場合、または認証されていないユーザーがイベント ハンドラーを実行 SelectedIndexChanged しようとすると、.NET ランタイムによって が発生 SecurityExceptionします。

セキュリティ コンテキストがメソッドの実行を承認されていない場合は、SecurityException がスローされます

図 14: セキュリティ コンテキストがメソッドの実行を承認されていない場合は、 SecurityException がスローされます (フルサイズの画像を表示する 場合は クリックします)

注意

複数のセキュリティ コンテキストが 1 つのクラスまたはメソッドにアクセスできるようにするには、クラスまたはメソッドを各セキュリティ コンテキストの 属性で PrincipalPermission 装飾します。 つまり、Tito と Bruce の両方でイベント ハンドラーを実行できるようにするには、次の RowDeleting2 つのPrincipalPermission 属性を追加します。

<PrincipalPermission(SecurityAction.Demand, Name:="Tito")> _

<PrincipalPermission(SecurityAction.Demand, Name:="Bruce")> _

多くのアプリケーションには、ASP.NET ページに加えて、ビジネス ロジックやデータ アクセス層など、さまざまなレイヤーを含むアーキテクチャもあります。 これらのレイヤーは通常、クラス ライブラリとして実装され、ビジネス ロジックとデータ関連の機能を実行するためのクラスとメソッドを提供します。 属性は PrincipalPermission 、これらのレイヤーに承認規則を適用する場合に役立ちます。

属性を PrincipalPermission 使用してクラスとメソッドの承認規則を定義する方法の詳細については、 Scott Guthrie のブログ エントリ「 を 使用したビジネスおよびデータ層への承認規則の追加」を参照 PrincipalPermissionAttributesしてください。

まとめ

このチュートリアルでは、ユーザーベースの承認規則を適用する方法について説明しました。 ASP の概要を見て開始しました。NET の URL 承認フレームワーク。 各要求で、ASP.NET エンジンは、アプリケーションの UrlAuthorizationModule 構成で定義されている URL 承認規則を調べて、要求されたリソースへのアクセスが ID に承認されているかどうかを判断します。 つまり、URL 承認を使用すると、特定のページまたは特定のディレクトリ内のすべてのページに対して承認規則を簡単に指定できます。

URL 承認フレームワークは、ページ単位で承認規則を適用します。 URL 承認では、要求する ID が特定のリソースへのアクセスを許可されているかどうか。 ただし、多くのシナリオでは、より細かい認可規則を呼び出します。 ページへのアクセスを許可されるユーザーを定義するのではなく、すべてのユーザーがページにアクセスできるようにする必要がありますが、ページにアクセスするユーザーに応じて異なるデータを表示したり、異なる機能を提供したりする必要があります。 通常、ページ レベルの承認では、許可されていないユーザーが禁止された機能にアクセスするのを防ぐために、特定のユーザー インターフェイス要素を非表示にする必要があります。 また、属性を使用して、特定のユーザーのクラスへのアクセスとそのメソッドの実行を制限することもできます。

プログラミングに満足!

もっと読む

このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。

著者について

複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 Scott は、 または mitchell@4guysfromrolla.com のブログから http://ScottOnWriting.NETアクセスできます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 に mitchell@4GuysFromRolla.com行をドロップしてください。