著者: ウィルムーブ && ヒース スチュワート
ホームページ: http://www.amuhouse.com
電子メール: [email protected]
注: 私は 2 か月前に ASP.NET を学んだばかりで、codeproject.com で「フォーム認証によるロールベースのセキュリティ」というタイトルの記事を見つけました。その時、私はそれを中国語に翻訳したいと思いました。しかし、直訳は本当につまらないので、この2日間、ヒース・スチュワートのこの記事を参考にして、自分なりの理解に基づいて、自分なりの考えと表現で中国語に書き上げました。この記事のために私が作成したデモ Web アプリケーションを添付します。
誤解がある場合は、指摘するかコメントを残してください。
P.S. スパムは本当に迷惑です、敬意を表してください。
元の記事はhttp://www.codeproject.com/aspnet/formsroleauth.aspにあります。
原作者ヒース・スチュワート
まとめ:
ASP.NET はロールベースの認証メカニズムを提供しますが、ロールのサポートは不完全です。この記事では、いくつかの例を通じて、このロールベースの認証メカニズムを実装および使用する方法を説明します。
はじめに:
ASP.NET のフォーム認証は、プラットフォームに依存しないシンプルなセキュリティ認証システムを実装するために少量のコードのみを必要とする非常に強力な機能です。
ただし、より複雑で効率的な認証メカニズムが必要な場合は、多くのユーザーをユーザー グループに分割することでその柔軟性を活用する必要があります。 Windows 統合認証はこの認証メカニズムを提供しますが、Windows NT LAN マネージャーである NTLM を使用するため、クロスプラットフォームではありません。現在、Linux システムを使用する人が増えており、Mozilla Forefox ブラウザのユーザーも増えています。これらの人々を締め出すことはできないため、別の認証メカニズムを探しています。 2 つのオプションがあります。1 つは、Web サイトを複数のエリアに分割し、複数のログイン ページを提供し、ユーザーを 1 人ずつ登録してログインさせる方法です。もう 1 つは、ユーザーをグループ化し、特定のユーザー グループのアクセス権を特定のページに制限する方法です。またはエリア。確かに後者の方が良い選択です。この機能は、個々のユーザーに役割を割り当てることで実現できます。
Microsoft は、.NET プラットフォームのフォーム認証にロールベースの認証メカニズムを残しましたが、これを独自に実装する必要があります。この記事では、その概念、実装、Web アプリケーションでの適用方法など、フォーム認証におけるロールベースの認証メカニズムに関するいくつかの基本事項を取り上げます。
必要な準備:
まず、データベース、Web アプリケーション プロジェクト、さまざまなセキュリティ レベルを持ついくつかの機密ディレクトリ、およびいくつかの ASP.NET ページを作成する必要があります。もちろん、これらを既存の Web アプリケーション プロジェクトに追加することもできます。
1. データベースを作成するには、
まず使用するデータベース管理システム DBMS を選択する必要があります。この記事では SQL Server 2000 を使用します。
実際のアプリケーション プロジェクトのデータベースには通常、ユーザー データ テーブル Users があり、ユーザーの一意のタグ: UserID、ユーザー名: UserName、パスワード: Password、ユーザーの電子メール アドレス: Email、ユーザーの都市: City、およびユーザーの数が含まれる場合があります。ユーザーログイン LoginCount などUserInRoles データ テーブル (通常、ユーザー名: UserName、ユーザー ロール: UserRoles の 2 つのフィールドが含まれます) を作成することで、ユーザーにロールを割り当てることができます。
わかりやすくするために、ユーザー データ テーブルのみを作成します。このテーブルには、ユーザー名 UserName、パスワード Password、およびユーザー ロール UserRoles の 3 つのフィールドがあります。テーブルを作成する前に、データベースを選択するか、新しいデータベースを作成する必要があります。 WebSolution という名前の新しいデータベースを作成するには、単純な SQL ステートメントのみが必要です。
プログラムコード
データベース Web ソリューションの作成
GO で
msdb というデータベースを選択するには
、次の SQL ステートメントを使用できます。
プログラムコード
msdbを使用する
行く
次に、先ほど説明した Users データ テーブルを作成します。SQL スクリプトは次のとおりです。
プログラム コード
Create TABLE Users。
(
ユーザー名 nvarchar(100) 制約 PK_ユーザー名 主キー、
パスワード nvarchar(150)、
ユーザーロール nvarchar(100)
)
このテーブルのインデックス資格情報を作成できます。 SQL ステートメントは次のとおりです。
プログラム コード
INDEX 資格情報の作成 ON ユーザー
(
ユーザー名、
パスワード
)
インデックスの作成はオプションであり、ユーザー自身が行うことができます。インデックス作成の利点と欠点については、関連情報を参照してください。
次に、この Users データベースにデータを追加します。キャラクター名は任意ですが、次のような意味のある名前を使用するのが最善です。
「Administrator」(最上位管理者)、「Manager」(管理者)、「Member」(参加メンバー)、「User」(一般ユーザー)など。例:
ユーザー名|パスワード|ロール
"willmove"|"pwd123"|"管理者、ユーザー"
"amuhouse"|"pwd123"|"User"
次のとおりです:
プログラム コード
-- '45CB41B32DCFB917CCD8614F1536D6DA' は、'pwd123' を使用して md5 によって暗号化された文字列であることに注意してください。
ユーザー (ユーザー名、パスワード、ユーザー役割) 値に挿入 ('willmove'、'45CB41B32DCFB917CCD8614F1536D6DA'、'管理者、ユーザー')
行く
ユーザー(ユーザー名、パスワード、ユーザーロール) 値に挿入 ('amuhouse','45CB41B32DCFB917CCD8614F1536D6DA','ユーザー')
行く
ロールは Web.config ファイル内で大文字と小文字が区別されるため、大文字と小文字が区別されることに注意してください。ここで、このセキュリティ認証メカニズムを実装するために必要なページをいくつか作成します。
1 つ目はユーザー ログイン ページ Login.aspx です。
Web アプリケーションをまだ作成していない場合は、今すぐ作成してください。もちろん、このページを既存の Web アプリケーションで作成することもできます。ここでは、RolebasedAuth という名前の Web アプリケーション (つまり、Visual Studio .Net のプロジェクト) が作成されていると仮定します。この Login.aspx をルート ディレクトリに置き、 http://localhost/RolebasedAuth/Login.aspxからアクセスできます。
この Login.aspx がどこに配置されるかは問題ではありませんが、一般の人がアクセスできる必要があります。
アプリケーションのルート パスの下に、Admin と User という 2 つの秘密のサブディレクトリを作成します。
次に、ロール認証をサポートするフォーム認証ログイン システムを作成します。 Microsoft は単純な実装メカニズムを提供していないため、時間をかけて自分で認証チケットを作成する必要があります。もちろん、少量の情報を保存する必要があります。一部の名前は Web.config で構成されているものと同じである必要があります。そうしないと、ASP.NET は認証チケットが無効であると判断し、ログイン ページに強制的にリダイレクトされます。 VS.NET の Login.aspx に 2 つの TextBox コントロールを追加し、UserNameTextBox と PasswordTextBox という名前を付けます。また、ボタンを追加して LoginButton という名前を付けます。これをクリックしてバックグラウンド コードを入力します。 LoginButton_Click メソッドに必要なコードを追加します。次のように:
プログラムコード
private void LoginButton_Click(オブジェクト送信者、System.EventArgs e)
{
//フォーム認証を初期化する
// System.Web.Security 名前空間にあることに注意してください
// したがって、コードの先頭に using System.Web.Security を追加します。
FormsAuthentication.Initialize ();
// データベース接続およびデータベース操作コマンド オブジェクトを作成します。
// System.Data.SqlClient 名前空間にあることに注意してください
// したがって、コードの先頭に using System.Data.SqlClient を追加します。
SqlConnection接続 =
new SqlConnection("データ ソース = sun-willmove;統合セキュリティ = SSPI;初期カタログ = WebSolution;");
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = " UserName=@usernameのユーザーから UserRoles を選択 " +
"ANDパスワード=@パスワード";
// 各パラメータを入力します
cmd.Parameters.Add("@username", SqlDbType.NVarChar, 100).Value =
ユーザー名テキストボックス.テキスト;
cmd.Parameters.Add("@パスワード", SqlDbType.NVarChar, 150).Value =
FormsAuthentication.HashPasswordForStoringInConfigFile(
PasswordTextBox.Text, "md5"); // または "sha1"
// データベース操作コマンドを実行します
conn.Open();
SqlDataReader リーダー = cmd.ExecuteReader();
if (reader.Read())
{
// 認証を実装するには、新しいチケットを作成します
FormsAuthenticationTicket チケット = new FormsAuthenticationTicket(
1, // チケットのバージョン番号
UserNameTextBox.Text, // チケット所有者
DateTime.Now, //チケットを割り当てる時間
DateTime.Now.AddMinutes(30), //有効期限
true, // ユーザーの Cookie が必要です
Reader.GetString(0), // ユーザー データ、ここが実際のユーザーのロールです
FormsAuthentication.FormsCookiePath);//有効な Cookie パス
//安全な送信のためにマシン コードのマシン キーを使用して Cookie を暗号化します
文字列ハッシュ = FormsAuthentication.Encrypt(ticket);
HttpCookie クッキー = 新しい HttpCookie(
FormsAuthentication.FormsCookieName, // 認証 Cookie の名前
hash); //暗号化されたクッキー
//チケットの有効期限と一致するようにクッキーの有効期限を設定します
if (ticket.IsPersistent) cookie.Expires = ticket.Expiration
// ページのリクエスト応答に Cookie を追加します。
Response.Cookies.Add(cookie);
// ユーザーを以前にリクエストしたページにリダイレクトします。
// これまでにページがリクエストされていない場合は、ホームページにリダイレクトします
文字列 returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl == null) returnUrl = "./";
// FormsAuthentication.RedirectFromLoginPage メソッドを呼び出しません。
// 追加したばかりのチケット (Cookie) を置き換えるため
Response.Redirect(returnUrl);
}
それ以外
{
// ユーザーに「パスワードが間違っています」と伝えないでください。これは侵入者にチャンスを与えることと同じです。
// 入力したユーザー名が存在することを知っているため
//
ErrorLabel.Text = "ユーザー名またはパスワードが間違っています。もう一度お試しください。";
ErrorLabel.Visible = true;
Reader.Close
();
conn.Close();
フロントエンドの aspx ページのコードは次のとおりです
。
プログラムコード
<%@ Page language="c#" Codebehind="Login.aspx.cs" AutoEventWireup="false" Inherits="RolebasedAuth.Login" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<頭>
<title>ログイン</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content=" http://schemas.microsoft.com/intellisense/ie5 ">
</HEAD>
<本文>
<form id="Form1" Method="post" runat="server">
<P>
<asp:Label id="Label1" runat="server">ユーザー名:</asp:Label>
<asp:TextBox id="UserNameTextBox" runat="server"></asp:TextBox></P>
<P><FONT face="宋体"> </FONT>
<asp:Label id="Label2" runat="server">パスワード:</asp:Label>
<asp:TextBox id="PasswordTextBox" runat="server" TextMode="Password"></asp:TextBox></P>
<P>
<asp:Label id="ErrorLabel" runat="server" Visible="False"></asp:Label></P>
<P>
<asp:Button id="LoginButton" runat="server" Text="Login"></asp:Button></P>
</form>
</body>
</HTML>
上記のパスワードで何をしたか、つまりハッシュ化していることがわかります。ハッシュ暗号化は、一意の文字配列を生成する一方向アルゴリズム (不可逆的) です。したがって、パスワードの大文字と小文字を 1 文字でも変更すると、まったく異なるハッシュ列が生成されます。これらの暗号化されたパスワードはデータベースに保存されるため、安全性が高まります。実際のアプリケーションでは、ユーザーの忘れたパスワードを取得したい場合があります。ただし、ハッシュ化は元に戻せないため、元のパスワードを回復することはできません。ただし、ユーザーのパスワードを変更し、変更したパスワードをユーザーに伝えることはできます。 Web サイトが古いパスワードを提供する可能性がある場合は、ユーザー データが安全ではないことを明確に考える必要があります。実際、国内の Web サイトのほとんどは、ユーザーのパスワードを暗号化せずにデータベースに直接保存しています。ハッカーが成功すると、これらのユーザー アカウントは危険にさらされます。
SSL を使用しない場合、パスワードはネットワーク上でクリア テキストで送信されます。通信中に盗まれる可能性があります。サーバー側でのパスワードの暗号化は、パスワード保管場所のセキュリティのみを保証します。 SSL 関連の情報は、 http://www.versign.comまたはhttp://www.thewte.comでご覧いただけます。
パスワードを暗号化してデータベースに保存したくない場合は、上記のコードを次のように変更できます。
FormsAuthentication.HashPasswordForStoringInConfigFile(PasswordTextBox.Text, "md5") を PasswordTextBox.Text に変更できます。
次に、Global.asax ファイルを変更する必要があります。 Web アプリケーションにこのファイルがない場合は、Web アプリケーション プロジェクトを右クリックし、[追加]->[新しい項目の追加...]->[グローバル アプリケーション クラス]を選択してください。 Global.asax または Global.asax.cs で、Application_AuthenticationRequest というメソッド (関数) を見つけます。まず、System.Security.Principal および System.Web.Security 名前空間が含まれているか、使用されていることを確認してから、変更されたコードを変更します。
プログラムコード
protected void Application_AuthenticateRequest(オブジェクト送信者, EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity が FormsIdentity である)
{
フォームアイデンティティ ID =
(FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
// チケットに保存されているユーザー データを取得します。これは実際にはユーザーのロールです。
文字列 userData = ticket.UserData;
string[] ロール = userData.Split(',');
HttpContext.Current.User = 新しい GenericPrincipal(id, ロール);
}
}
}
}
認証チケット (ユーザー名とパスワード) は Cookie の一部として保存されません。また、ユーザーは Cookie を変更できるため、保存することはできません。
実際、FormsAuthentication はマシン キー (通常は machine.config 内) を使用してチケット (FormsAuthenticationTicket) を暗号化します。 UserData を使用してユーザー ロールを保存し、新しい認証情報を生成します。資格情報が作成されると、現在のコンテキスト (つまり HttpContext) に追加され、ユーザーのロールを取得するために使用できるようになります。
次に、シークレット ディレクトリ (管理者などの特定のユーザーのみがアクセスできるディレクトリである「セキュリティ ディレクトリ」) を設定します。まず、Web アプリケーションのルート ディレクトリに Web.config ファイルがあるかどうかを確認し、存在しない場合は作成します。サブディレクトリに Web.config ファイルを作成することもできます。もちろん、この Web.config ファイルは制限されています (一部のパラメータは設定できません)。
セキュリティ認証を実装するには、Web アプリケーションのルート ディレクトリにある Web.config ファイルの <system.web> ノードの下にある
プログラム コードを
見つけます。
<authentication mode="Windows" /> を
<authentication mode="Forms">
に変更します。
<forms name="AMUHOUSE.ASPXAUTH"
loginUrl="ログイン.aspx"
保護 = "すべて"
パス="./" />
</認証>
<認可>
<allow users="*"/>
</authorization>
上記の name="AMUHOUSE.ASPXAUTH" では、AMUHOUSE.ASPXAUTH という名前は任意です。ユーザーまたはユーザー グループのアクセス許可を制御するには、アプリケーションのルート ディレクトリに Web.config ファイルを構成する方法と、シークレット ディレクトリに独立した Web.config ファイルを作成する方法があります。 (後者の方が良いかもしれません。) 前者の場合、Web.config には次のコンテンツ (または同様のコンテンツ) が含まれている必要があります。
プログラムコード
<構成>
<システム.ウェブ>
<認証モード="フォーム">
<forms name="AMUHOUSE.ASPXAUTH"
loginUrl="ログイン.aspx"
保護 = "すべて"
パス="/"/>
</認証>
<認可>
<allow users="*"/>
</認可>
</system.web>
<場所のパス="./Admin">
<システム.ウェブ>
<認可>
<!-- 注意!次の行の順序と大文字小文字は非常に重要です。 -->
<allowroles="管理者"/>
<拒否ユーザー="*"/>
</認可>
</system.web>
</場所>
<場所のパス="./ユーザー">
<システム.ウェブ>
<認可>
<!-- 注意!次の行の順序と大文字小文字は非常に重要です。 -->
<allow role="ユーザー"/>
<拒否ユーザー="*"/>
</認可>
</system.web>
</場所>
</設定>
Web アプリケーションのディレクトリが相互に依存しないようにし、名前の変更や移動を容易にするために、各セキュリティ サブディレクトリに個別の Web.config ファイルを構成することを選択できます。次のように <authorization/> ノードを構成するだけで済みます。
プログラムコード
<構成>
<システム.ウェブ>
<認可>
<!-- 注意!次の行の順序と大文字小文字は非常に重要です。 -->
<allowroles="管理者"/>
<拒否ユーザー="*"/>
</認可>
</system.web>
</設定>
便宜上、上記の役割では大文字と小文字が区別されることを再度思い出してください。
<allow role="管理者,管理者" />
このディレクトリへの複数のロールのアクセスを許可または拒否する場合は、次のようにカンマで区切ることができます。
<allow role="管理者,メンバー,ユーザー" />
<deny users="*" />
この時点で、Web サイトにロールベースのセキュリティ認証メカニズムを構成しました。まずプログラムをコンパイルしてから、 http://localhost/RolebasedAuth/Adminなどのシークレット ディレクトリへのアクセスを試行すると、ユーザー ログイン ページにリダイレクトされます。ログインに成功し、自分の役割にこのディレクトリへのアクセス権がある場合は、このディレクトリに戻ります。機密ディレクトリに入ろうとしているユーザー (または侵入者) がいる可能性があります。セッションを使用してユーザーのログイン回数を保存できます。その回数が一定の回数を超えると、ユーザーはログインできなくなります。 「システムはログイン要求を拒否しました!」と表示されます。
以下では、ユーザーの役割に基づいて Web コントロールに異なるコンテンツを表示させる方法について説明します。
場合によっては、ユーザーの役割に基づいてコンテンツを表示する方がよい場合があります。これは、非常に多くの異なる役割 (ユーザー グループ) に対して重複コンテンツを多く含むページを大量に作成したくないからです。このようなサイトでは、さまざまなユーザー アカウントが共存でき、有料ユーザー アカウントは追加の有料コンテンツにアクセスできます。別の例は、現在のユーザーが「管理者」ロールに属している場合に、管理者ページにリンクする「管理者に入る」ボタンを表示するページです。これからこのページを実装していきます。
上で使用した GenericPrincipal クラスは IPincipal インターフェイスを実装しています。このインターフェイスには IsInRole() というメソッドがあり、そのパラメーターは検証されるユーザー ロールです。ロールが「管理者」であるログインユーザーにコンテンツを表示したい場合は、Page_Load に次のコードを追加します。
プログラムコード
if (User.IsInRole("管理者"))
AdminLink.Visible = true;
ページ全体のコードは次のとおりです (わかりやすくするために、背景コードも aspx ページに記述されています)。
プログラムコード
<html>
<頭>
<タイトル>ようこそ! </タイトル>
<script runat="サーバー">
protected void Page_Load(オブジェクト送信者, EventArgs e)
{
if (User.IsInRole("管理者"))
AdminLink.Visible = true;
それ以外
AdminLink.Visible = false;
}
</script>
</head>
<本文>
<h2>ようこそ! </h2>
<p>アミュハウスへようこそhttp://amuhouse.com/ ^_^</p>
<asp:HyperLink id="AdminLink" runat="サーバー"
Text="管理者ホームページ" NavigateUrl="./Admin"/>
</body>
</html>
このようにすると、Admin ディレクトリにリンクされた HyperLink コントロールは、管理者の役割を持つユーザーにのみ表示されます。ログインしていないユーザーに、次のようなログイン ページへのリンクを提供することもできます。
プログラムコード
protected void Page_Load(オブジェクト送信者, System.EventArgs e)
{
if (User.IsInRole("管理者"))
{
AdminLink.Text = "管理者、入ってください";
AdminLink.NavigateUrl="./Admin";
}
else if(User.IsInRole("ユーザー"))
{
AdminLink.Text = "登録ユーザーは入力してください";
AdminLink.NavigateUrl="./ユーザー"
;
それ以外
{
AdminLink.Text = "ログインしてください";
AdminLink.NavigateUrl="Login.aspx?ReturnUrl=" + Request.Path;
}
}
ここで、ReturnUrl という QueryString 変数を設定することで、ログイン成功後にユーザーを現在のページに戻すことができます。
まとめ:
この記事は、ロールベースのセキュリティ メカニズムの重要性と実用性を理解するのに役立ち、また、ASP.NET を使用してロールベースのセキュリティ メカニズムを実装します。これは実装が難しいメカニズムではありませんが、ユーザー資格情報とは何か、ユーザーを認証する方法、および許可されたユーザーを認証する方法についてある程度の知識が必要になる場合があります。お役に立てれば幸いです。 Web サイトにロールベースのフォーム セキュリティ認証を実装する際のガイドになれば幸いです。
添付:
この記事のサンプル プロジェクト ソース コード: