C#アプリケーションに一般的なセキュリティを実装する方法を知る必要があります。これに関してどのようなオプションがありますか?既存のフレームワークが私のニーズを満たしている場合は、それを使用したいと思います。車輪を作り直したくありません。
私の要件は次のとおりです。
.Netコミュニティによって古くから使用されてきた無料のオープンソースフレームワーク/ライブラリを探しています。
私のアプリケーションはクライアント/サーバーアプローチを採用しており、サーバーはWindowsサービスとして実行され、SQL Serverデータベースに接続しています。クライアントとサーバー間の通信はWCFを介して行われます。
重要なもう1つのことは、特定のエンティティを表示、更新、削除するための特定のユーザーまたはロールのアクセス許可を、それが顧客であろうと製品であろうと、割り当てられるようにする必要があることです。ジャックは10人中3人の顧客を表示できますが、Microsoft、Yahoo、およびGoogleの顧客の詳細のみを更新でき、Yahooのみを削除できます。
大まかなセキュリティでは、組み込みのプリンシパルコードが役立つ場合があります。ユーザーオブジェクト(およびそれらのロール)は、「プリンシパル」によって.NETで制御されますが、ランタイム自体がこれを強制できるので便利です。
プリンシパルの実装は実装で定義することができ、通常は独自のものを挿入できます。 たとえば、WCF 。
大まかなアクセスを実行するランタイム(つまり、どのfunctionalityにアクセスできますが、特定のdata):
static class Roles {
public const string Administrator = "ADMIN";
}
static class Program {
static void Main() {
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), new string[] { Roles.Administrator });
DeleteDatabase(); // fine
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Barney"), new string[] { });
DeleteDatabase(); // boom
}
[PrincipalPermission(SecurityAction.Demand, Role = Roles.Administrator)]
public static void DeleteDatabase()
{
Console.WriteLine(
Thread.CurrentPrincipal.Identity.Name + " has deleted the database...");
}
}
ただし、これはきめ細かなアクセスには役立ちません(つまり、「フレッドは顧客Aにアクセスできますが、顧客Bにはアクセスできません」)。
追加;もちろん、きめ細かい場合は、プリンシパルのIsInRole
をチェックすることで、実行時に必要なロールを簡単にチェックできます。
static void EnforceRole(string role)
{
if (string.IsNullOrEmpty(role)) { return; } // assume anon OK
IPrincipal principal = Thread.CurrentPrincipal;
if (principal == null || !principal.IsInRole(role))
{
throw new SecurityException("Access denied to role: " + role);
}
}
public static User GetUser(string id)
{
User user = Repository.GetUser(id);
EnforceRole(user.AccessRole);
return user;
}
また、ロールの遅延テスト/キャッシングを行う独自のプリンシパル/アイデンティティーオブジェクトを作成することもできます。
class CustomPrincipal : IPrincipal, IIdentity
{
private string cn;
public CustomPrincipal(string cn)
{
if (string.IsNullOrEmpty(cn)) throw new ArgumentNullException("cn");
this.cn = cn;
}
// perhaps not ideal, but serves as an example
readonly Dictionary<string, bool> roleCache =
new Dictionary<string, bool>();
public override string ToString() { return cn; }
bool IIdentity.IsAuthenticated { get { return true; } }
string IIdentity.AuthenticationType { get { return "iris scan"; } }
string IIdentity.Name { get { return cn; } }
IIdentity IPrincipal.Identity { get { return this; } }
bool IPrincipal.IsInRole(string role)
{
if (string.IsNullOrEmpty(role)) return true; // assume anon OK
lock (roleCache)
{
bool value;
if (!roleCache.TryGetValue(role, out value)) {
value = RoleHasAccess(cn, role);
roleCache.Add(role, value);
}
return value;
}
}
private static bool RoleHasAccess(string cn, string role)
{
//TODO: talk to your own security store
}
}
私の答えはおそらくこの質問の答えに依存しています:これはActive Directoryを使用してネットワーク内に存在するエンタープライズアプリケーションですか? =
答えが「はい」の場合、これらは私が提供するステップです:
1)アプリケーションのグローバルグループを作成します。私の場合、APPUSERグループとAPPADMINグループがありました。
2)SQL ServerにMIXED AUTHENTICATIONモードでアクセスできるようにしてから、APPUSERグループをSQL SERVER LOGINとしてデータベースに割り当て、DBへの適切なCRUD権限を付与して、アクセスできることを確認します。接続文字列にTrusted Connection = Trueを含むSQLサーバー.
この時点で、ADストアが認証を担当します。 TRUSTED CONNECTIONを介してアプリケーションにアクセスしているため、アプリケーションを実行しているアカウントのIDがSQL Serverに渡されます。
AUTHORIZATION(つまり、ログインしているユーザーに許可されていることをアプリケーションに伝える)の場合は、ログインしているユーザーがメンバーであるグループのリストをADに照会するだけです。次に、適切なグループ名を確認し、この方法でメンバーシップに基づいてUIを構築します。
したがって、私のアプリケーションの動作は次のとおりです。
次に、決定された権限などを含むPRINCIPLEオブジェクトを持っているか、フォームを構築するときにアクセスできるGLOBAL変数を使用して適切なUIを決定します(つまり、ユーザーがADMINグループのメンバーでない場合は、すべての[削除]ボタンを非表示にします)。
なぜこれを提案するのですか?
それは展開の問題です。
私の経験では、ほとんどのエンタープライズアプリケーションはプログラマーではなくネットワークエンジニアによって展開されています。したがって、認証/承認をADの責任とすることは理にかなっています。それは、認証/承認について話し合うときにネットワーク担当者が行く場所だからです。
さらに、ネットワークの新しいユーザーの作成中、ネットワークエンジニア(または新しいネットワークユーザーの作成を担当する人)は、ADにいる間、グループに割り当てる必要があるという事実よりも、グループの割り当てを実行することを覚えやすくなります。承認の割り当てを解析する12のアプリケーション。
これを行うことで、新入社員に付与する必要がある、または会社を辞める必要がある許可や権利の迷路を解消し、所属する中央リポジトリ(つまり、AD @ドメインコントローラーレベル)で認証と承認を維持できます。
ASP.NETのメンバーシッププロバイダー を調べます。私はそのままのSQLMembershipProviderがあなたのケースで動作するとは思いませんが、あなた自身のプロバイダーをロールするのは簡単です。
私はCSLA.netのようなものを見てみましょう: Expert C#2008 Business Objects
それはあなたが必要とするすべてを提供するはずです。
WCFには、承認と認証の両方を提供する豊富なセキュリティ関連機能があります。詳細はこちら: http://msdn.Microsoft.com/en-us/library/ms735093.aspx
ここではいくつかの個別の問題を検討していると思います。ほとんどのセキュリティシステムが認証と認可を別々に扱っているのは偶然ではありません。
認証の場合、より大きな問題はロジスティックです。または、これらのユーザーが住むのに論理的な場所があります。それは、アプリケーションのローカル、Active Directory、その他のLDAPストア、またはその他のアプリケーションにさえあります。正確にどこが重要でないか-ユーザーを確実に識別でき、できればそのタスクを他の誰かの問題にできる必要があるだけです。 1日の終わりには、一意の識別子と、会計からのボブが会計からのボブであるという快適さが本当に必要です。
ここでは、承認が問題のより興味深い部分です。本当にきめ細かいのであれば、ユーザーがどこから来たとしても、アプリケーション内で完全に管理したいと思うでしょう。 Marc Gravellは、少なくともこの一部をモデル化する良い方法に本当に思い当たりました。物事を管理するためにIPrincipalとPrincipalPermissionのカスタム実装を使用することは、開始するのに非常にクリーンな方法です。さらに、 this one のような手法を使用して、かなり複雑な方法でより複雑な承認決定を行うことができます。
すべての要件に対するソリューションとして、「RBAC」(役割ベースのアクセス制御システム)という用語を使用します。
ここでは「RBAC」について詳しく説明するのではなく、簡単に次のように説明します。
基本的に3つの機能が含まれています。
1)認証-ユーザーの身元を確認します。通常、これはユーザーアカウントとパスワードまたは資格情報を介して行われます。
2)承認-アプリケーションでユーザーが実行できることと実行できないことを定義します。例「注文の変更」は許可されていますが、「新しい注文の作成」は許可されていません。
3)アプリケーションに対するユーザーアクションの監査。 -アプリケーションに対するユーザーのアクション、および誰がどのユーザーにどのアクセスを許可したかを追跡しますか?
ここのwikiでRBACをチェックできます。
https://en.wikipedia.org/wiki/Role-based_access_control
ここで、要件への回答に関して-可能な解決策の1つは、ニーズに応じてASP.NETメンバーシップを拡張することです。
そして、いくつかのすぐに使用できるフレームワークについて、私はお勧めします VisualGuard 動作するため、これをチェックする必要があります。セントラル管理コンソールを介したすべてのユーザー、ロール、権限、およびアプリケーション。権限を定義するために、管理者は開発者の知識を必要としません。つまり、UIを介してアクティビティに制限を作成できます。
この記事をチェックして、権限と役割ベースのシステムについて理解を深めることもできます。