1 設計アイデア
拡張性の高い一連のユーザー認証管理を設計するには、ユーザー、ロール、権限などのデータベース テーブルを確立し、それらの間の関係を確立する必要があります。具体的な実装は次のとおりです。 1.1 ユーザー ユーザーは単なる純粋なユーザーであり、ユーザー名、パスワードなどのユーザー関連情報を記録するために使用され、権限は分離されています。特定のリソースに対する権限を持つには、ユーザーをロールに関連付ける必要があります。 ユーザーは通常、次の属性を持っています: ü システム内で一意の番号。 ü システム内で一意の名前。 ü ユーザーのパスワード。 ü 注釈、ユーザーまたは役割を説明する情報。 1.2 キャラクター ロールは権限の基本単位であり、ユーザーには通常、次の属性が与えられます。 ü システム内で一意の番号。 ü システム内で一意の名前。 ü コメント、キャラクター情報の説明 1.3 権限 色の権限は、ファイルの読み取り、書き込み、変更、削除の機能など、役割に応じてプログラムの特定の機能を取得するためのユーザーの操作を指し、通常は次の属性を持ちます: ü システム内で一意の番号。 ü システム内で一意の名前。 ü コメント、許可情報を説明します 1.4 ユーザーとロールの関係 ユーザー (User) は複数のロール (Role) に属することができ、ロール グループは複数のユーザーを持つこともできます。ユーザー ロールは、ユーザー間の所属関係を記述するために使用されるオブジェクトです。ユーザーは、 などのロールに関連付けられた特定のリソースに対する権限を持っています。 l ユーザー (ユーザー): ユーザーID ユーザー名 UserPwd 1 2 …… l 役割: ロールID経由 01 システム管理者 監視 システム保守管理者 02 監視スタッフ オンライン監視スタッフ 03 スケジュールスタッフ スケジュールスタッフ 04 一般スタッフスタッフ … l ユーザー役割 (User_Role): UserRoleID out through fろさん 张1 1 01 ユーザー「Zhang San」は「システム管理者」の役割に割り当てられました 李2 2 02 ユーザー「Li Si」は「監視スタッフ」の役割に割り当てられました 2 …… この関係テーブルから、ユーザーが所有する特定のリソースをユーザーの役割を通じて関連付けることができることがわかります。 1.5 権限と役割の関係 1 つのロールには複数の権限を設定でき、同じ権限を複数のロールに割り当てることができます。例: l 役割: ロールIDオフ。 01 システム管理者 監視 システム保守管理者 02 監視スタッフ オンライン監視スタッフ 03 スケジュールスタッフ スケジュールスタッフ 04 一般スタッフスタッフ … l 許可: 権限ID 権限名 権限メモ 0001 監視の追加 監視オブジェクトを追加できます 0002 監視の変更 監視オブジェクトの変更を許可します 0003 監視の削除 監視オブジェクトの削除を許可します 0004 監視情報の表示 監視オブジェクトの表示を許可します …… l Role_Permission: RolePermissionIDRoleIDPermissionIDRolePermissionNote 1 2 33 01 0003 文字「システム管理者」には「監視の削除」権限があります 4 01 0004 文字「システム管理者」には「監視の検査」権限があります 15 02 0001 役割「監視担当者」、権限「監視の強化」 46 02 0004 役割「監視担当者」、権限「監視の検査」 …… 上記の例のロール権限関係から、ロール権限によってロールと権限の間に対応関係を確立できることがわかります。 1.6 ユーザー権限を作成する ユーザー権限システムの中核は、権限の作成、権限の割り当て、権限の使用の 3 つの部分で構成されます。 最初のステップは、クリエイターが権限 (Permission) を作成することです。これは、クリエイターがシステムを設計および実装するときに分割されます。ストアド プロシージャ CreatePermissionInfo (@PermissionName, @PermissionNote) を使用して権限情報を作成し、システム モジュールが持つ権限を指定します。 2 番目のステップは、システム管理者 (Administrator) がユーザーとロールを作成し、ユーザーのロール (User-Role) とロールの権限 (Role-Permission) の関係を指定することです。1) ユーザーの作成、ユーザーの変更、ユーザーの削除の機能があります: 管理者
l ストアド プロシージャ CreateUserInfo (@UserName, @UserPwd) はユーザー情報を作成します。 l ストアド プロシージャ ModifyUserInfo (@UserName, @UserPwd) はユーザー情報を変更します。 l ストアド プロシージャ DeleteUserInfo (@UserID) はユーザー情報を削除します。 2) ロールの作成とロールの削除の機能があります: 管理者l ストアド プロシージャ CreateRoleInfo (@RoleName, @RoleNote) はロール情報を作成します。 l ストアド プロシージャ DeleteRoleInfo(@RoleID) はロール情報を削除します。
3) 管理者には、ユーザーと役割、役割と権限の間の関係を確立する機能があります: l ストアド プロシージャ GrantUserRole (@UserID、@RoleID、@UserRoleNote) は、ユーザーとロール間の関係を確立します。 l ストアド プロシージャ DeleteUserRole(@UserRoleID) は、ユーザーとロール間の関連付けを削除します。 l ストアド プロシージャ GrantRolePermission(@RoleID,@PermissionID,@RolePermissionNote) は、ロールと権限の間の関係を確立します。 l ストアド プロシージャ DeleteRolePermission(@RolePermissionID) は、ロールと権限の間の関係を削除します。 3 番目のステップは、ユーザーが管理者によって割り当てられた権限を使用して各システム モジュールを使用することです。ストアド プロシージャ GetUserRole (@UserID、@UserRoleID 出力)、GetRolePermission (@RoleID、@Role-) を使用します。 -PermissinID 出力) は、モジュールを使用するためのユーザーの許可を取得します。 1.7 ユーザー認証の実装 ユーザーが検証に合格すると、システムは 128 ビットの TicketID を自動的に生成してユーザー データベース テーブルに保存し、ユーザー認証用のストアド プロシージャ Login (@UserID、@UserPwd、@TicketID 出力) を確立します。合格した場合、TicketID が取得されます。そうでない場合、TicketID は null になります。フローチャートは次のとおりです: 図1 ログインフローチャート TicketID を取得した後、クライアントはサーバー メソッドを呼び出すときに TicketID を渡し、ストアド プロシージャ JudgeTicketPermission (@TicketID, @PermissionID) を通じて TicketID に対応するユーザーの権限を決定し、その権限に基づいてメソッド呼び出しを行います。 ユーザーがシステムを終了するとき、ストアド プロシージャ Logout (@UserID) を作成してシステムを終了します。ユーザーがシステムを異常終了すると、最終ログイン時刻 (LastSignTime) に基づいてユーザーの TicketID が決定され、ユーザーの異常終了を処理するストアド プロシージャ ExceptionLogout (@UserID, @LastSignTime) が確立されます。 図 2 ログアウトのフローチャート WebService は SoapHeader を使用して TicketID を書き込み、クライアントからサーバーに TicketID を渡すことができます。 .Net Remoting は、CallContext クラスを使用して、クライアントからサーバーに TicketID を渡すことができます。 2 データベース設計 2.1 データベーステーブル 図 3 データベース関係図 2.2 データベーステーブルの説明 2.2.1 ユーザーテーブル(Static_User) 静的ユーザーStatic_User フィールド名
| タイプ
| 備考
|
ユーザーID |
| varchar(20)
| PK
|
ユーザー名 |
| varchar(20)
|
|
ユーザーパスワード |
varchar(20) |
|
||
ラストサインタイム |
最終ログイン時間 |
データ時間 |
|
SignState |
ユーザーログインステータスマーク |
int |
|
チケットID |
検証チケットレコード番号 |
varchar(128) |
|
|
|
|
|
2.2.2 ロールテーブル(Static_Role) 静的役割
Static_User フィールド名 |
詳しい説明 |
タイプ |
備考 |
ロールID |
文字番号 |
varchar(20) |
PK |
役割名 |
キャラクター名 |
varchar(20) |
|
ロールノート |
キャラクター情報説明 |
varchar(20) |
|
|
|
|
|
2.2.3 ユーザーロールテーブル(Static_User_Role) 静的ユーザーロール
Static_User フィールド名 |
詳しい説明 |
タイプ |
備考 |
ユーザーロールID |
ユーザー役割番号 |
varchar(20) |
PK |
ユーザーID |
ユーザーID |
varchar(20) |
FK |
ロールID |
文字番号 |
varchar(20) |
FK |
ユーザーロールノート |
ユーザー役割情報の説明 |
varchar(20) |
|
|
|
|
|
2.2.4 パーミッションテーブル(Static_Permission) 静的_許可
Static_User フィールド名 |
詳しい説明 |
タイプ |
備考 |
許可ID |
番号 |
varchar(20) |
PK |
権限名 |
権限名 |
varchar(20) |
|
許可に関する注意事項 |
ホログラフィック情報の説明 |
varchar(20) |
|
|
|
|
|
2.2.5 ロール権限テーブル(Static_Role_Permission) 静的_役割_許可
Static_User フィールド名 |
詳しい説明 |
タイプ |
備考 |
ロール権限ID |
ロール許可番号 |
varchar(20) |
PK |
ロールID |
文字番号 |
varchar(20) |
FK |
許可ID |
許可番号 |
varchar(20) |
FK |
役割権限メモ |
ロール権限情報の説明 |
varchar(20) |
|
|
|
|
|
3 .net技術概要 3.1 WebサービスのSoapHeader SQL データベースに対してカスタム認証と認可を実行します。この場合、カスタム資格情報 (ユーザー名やパスワードなど) をサービスに渡し、サービス自体に認証と認可を処理させる必要があります。 XML Web サービスへのリクエストとともに追加情報を渡す簡単な方法は、SOAP ヘッダーを使用することです。これを行うには、サービス内で SOAPHeader から派生したクラスを定義し、サービスのパブリック フィールドをその型に宣言します。これはサービスのパブリック コントラクトで公開されており、次の例に示すように、WebServiceUtil.exe からプロキシを作成するときにクライアントが利用できます。
リーリー
System.Web.Services の使用;
System.Web.Services.Protocols の使用;
// AuthHeader クラスは SoapHeader から拡張されます
パブリック クラス AuthHeader : SoapHeader {
公開文字列ユーザー名;
公開文字列パスワード;
}
パブリック クラス HeaderService : WebService {
public AuthHeader sHeader;
…
} サービス内の各 WebMethod は、SoapHeader カスタム プロパティを使用して、関連するヘッダーのセットを定義できます。デフォルトではヘッダーは必須ですが、オプションのヘッダーを定義できます。 SoapHeader プロパティは、クライアント クラスまたはサーバー クラスのパブリック フィールドまたはプロパティの名前を指定します (このタイトルでは Headers プロパティと呼びます)。 WebService は、入力ヘッダーのメソッドを呼び出す前に Headers プロパティの値を設定します。WebService は、メソッドが出力ヘッダーを返すときに値を取得します。[WebMethod(Description="このメソッドには呼び出し元によって設定されたカスタム SOAP ヘッダーが必要です")]
[SoapHeader("sHeader")]
パブリック文字列 SecureMethod() {
if (sHeader == null)
return "エラー: 認証情報を入力してください";
その他
return "USER: " + sHeader.Username;
}
次に、次の例に示すように、クライアントはヘッダーを必要とするメソッドを呼び出す前に、プロキシ クラスにヘッダーを直接設定します。 HeaderService h = new HeaderService();AuthHeader myHeader = new AuthHeader();
myHeader.Username = "ユーザー名";
myHeader.Password = "パスワード";
h.AuthHeader = myHeader;
文字列結果 = h.SecureMethod();
3.2 .Net Remotingのセキュリティ認証方法
CallContext は、実行コード パスとともに渡される一連のプロパティを提供します。 CallContext は、メソッド呼び出しのスレッド ローカル ストレージに似た専用のコレクション オブジェクトであり、各論理実行スレッドに固有のデータ スロットを提供します。データ スロットは、他の論理スレッド上の呼び出しコンテキスト間では共有されません。 CallContext が実行コード パスに沿って伝播し、そのパス内のさまざまなオブジェクトによって検査されるときに、オブジェクトを CallContext に追加できます。別の AppDomain 内のオブジェクトに対してリモート メソッド呼び出しが行われると、CallContext クラスによって、リモート呼び出しとともに伝播される LogicalCallContext インスタンスが生成されます。 ILogicalThreadAffinative インターフェイスを公開し、CallContext に格納されているオブジェクトのみが、LogicalCallContext の AppDomain の外に伝播されます。このインターフェイスをサポートしないオブジェクトは、LogicalCallContext インスタンスのリモート メソッド呼び出しでは転送されません。 CallContext.SetData メソッドは、指定されたオブジェクトを保存し、指定された名前に関連付けます。CallContext.GetData メソッドは、指定された名前のオブジェクトを CallContext から取得します。 次のコード例は、SetData メソッドを使用して、識別のために本体オブジェクトと ID オブジェクトをリモートの場所に転送する方法を示しています。 パブリック クラス ClientClass {public static void Main() {
GenericIdentity ident = new GenericIdentity("Bob");
GenericPrincipal prpal = new GenericPrincipal(ident,
) ️LogicalCallContextData データ =
新しい LogicalCallContextData(prpal);
// CallContext にデータを入力します
CallContext.SetData("テストデータ", data);
Console.WriteLine(data.numOfAccesses);
ChannelServices.RegisterChannel(new TcpChannel());
RemotingConfiguration.RegisterActivatedClientType(
typeof(HelloServiceClass), "tcp://localhost:8082");
HelloServiceClass サービス = new HelloServiceClass();
if(service == null) {
Console.WriteLine("サーバーが見つかりませんでした。");
戻る;
}
// リモートメソッドを呼び出す
Console.WriteLine();
Console.WriteLine("リモートオブジェクトの呼び出し");
Console.WriteLine(service.HelloMethod("Caveman"));
Console.WriteLine(service.HelloMethod("Spaceman"));
Console.WriteLine(service.HelloMethod("Bob"));
Console.WriteLine("リモートオブジェクト呼び出しが完了しました");
Console.WriteLine();
//呼び出しコンテキストから返されたデータを抽出します
LogicalCallContextData returnsData =
(LogicalCallContextData)CallContext.GetData("テストデータ");
Console.WriteLine(data.numOfAccesses);
Console.WriteLine(returnedData.numOfAccesses);
}
}
次のコード例は、GetData メソッドを使用して、ホストとマーク付けオブジェクトをどのようにプロシージャの位置に転送するかを示します。 システムの使用;System.Text を使用する;
System.Runtime.Remoting.Messaging を使用する;
System.Security.Principal を使用する;
パブリッククラス HelloServiceClass : MarshalByRefObject {
static int n_instances;
int instanceNum;
public HelloServiceClass() {
n_instances++;
instanceNum = n_instances;
Console.WriteLine(this.GetType().Name + " が作成されました。
インスタンス番号 = {0}"、インスタンス番号);
}
~HelloServiceClass() {
Console.WriteLine("
のインスタンス {0} が破棄されました
HelloServiceClass."、instanceNum);}
public String HelloMethod(String name) {
//通話コンテキストデータを抽出します
LogicalCallContextData データ =
(LogicalCallContextData)CallContext.GetData("テスト データ");
IPrincipal myPrincipal = data.Principal;
// ユーザー ID を確認します
if(myPrincipal.Identity.Name == "ボブ") {
Console.WriteLine("nこんにちは、{0} さん、あなたは特定されました!",
myPrincipal.Identity.Name);
Console.WriteLine(data.numOfAccesses);
}
else {
Console.WriteLine("消えてください! あなたは識別されていません!");
戻る
}
//クライアントに結果を計算して返します
「「こんにちは」+名前+を返します。」;
4 詳細なコード設計 4.1 Webサービスのコード設計
WebService コードは主にデータベースを操作し、クライアントが呼び出すデータベースを操作するためにクライアントが必要とするメソッドを確立します。 1) class UserInfoMng() メソッドを含むユーザー情報管理クラス:
) を呼び出します
4.2 ユーザー認証コードの設計(クライアント側) クライアントは、WebService メソッドを呼び出してデータベースにアクセスします。クライアント コード設計では、主に、権限設定、ユーザー管理、ユーザー認可管理、ユーザー認証管理などのインターフェイスの機能を実装します。
1) 権限設定
class PermissionInfoMng() メソッドを含むユーザー権限情報管理クラス:
2) ユーザー管理
class UserInfoMng() メソッドを含むユーザー情報管理クラス:
l CreateUserInfo() ユーザー情報を作成します
l ModifyUserInfo() ユーザー情報を変更します
l DeleteUserInfo() ユーザー情報を削除します
3) ユーザー権限管理
class RoleInfoMng() ロール情報管理クラス (メソッドを含む):
l CreateRoleInfo() ロール情報を作成します
l DeleteRoleInfo() ロール情報を削除します
class UserRoleMng() ユーザー役割管理クラス (メソッドを含む):
l GrantUserRole() ユーザー役割を付与します
l DeleteUserRole() ユーザーロールを削除します
class rolePermissionMng() メソッドを含むロール権限管理クラス
l GrantRolePermission() ロール権限を付与します
l DeleteRolePermission() ロール権限を削除します
4) ユーザー認証管理 class Authentication() メソッドを含むユーザー認証クラス: l Login(string UserName string UserPwd) ユーザー認証後、TicketID がユーザーに割り当てられます。それ以外の場合、TicketID は null です l Logout() ユーザーは通常通りログアウトします