多くの役割を担うカスタムCodeaCcesSeCurityAttribute
-
27-10-2019 - |
質問
私はアプリのロールベースのセキュリティに取り組んでいますが、基本的にカスタマイズされたVerison MVCをやりたいと思っています AuthorizeAttribute
- ただし、MVCにリンクしないビジネスロジックレイヤーでのみ。
私は見ました PrincipalPermissionAttribute
しかし、封印されているときにカスタマイズする方法はないようです。メンバーシップをチェックできるカスタムバージョンを作成したいだけです どれか 複数の属性を使用せずに役割のリストのリストと、ロールメンバーシップの探索場所も定義します。
.netに私が足りないようなものはありますか?それとも、ASP.NETのauthorizeattribute/roleprovider/etcを再実装せずにこれを行う方法についての洞察を持っている人はいますか?
編集
現在、必須バージョンを実行していますが、メソッド/クラスの上に簡単に表示できるため、宣言的なアトリブバージョンをむしろ持っています。
今、私は私のビジネス層の抽象的な基本クラスに次のことを持っています:
protected void EnsureEditorLevelAccess()
{
var allowedRoles = new[]
{
Roles.Administrator,
Roles.Editor,
};
var roles = GetAccountRoles(GetCurrentUsername());
if (roles.Any(role => allowedRoles.Contains(role)))
{
return;
}
throw new SecurityException("You do not have sufficient privileges for this operation.");
}
私は使用できるのが好きです Roles.Administrator
などのロール名が恐ろしいため(Active Directory Group Based ...)、クラス/メソッドの上に登場できるカスタム属性のコンストラクターにそれらの詳細を包むことを考えていました。
GetAccountRoles
注射可能なロールプロバイダープロパティの上のファサードであり、データベースを使用するADまたはテストバージョンのいずれかを使用するように設定できます。
サブクラスができます Attribute
, 、しかし、それがどのようにセキュリティチェックを開始するかはわかりません。
解決
既存のプリンシパルメリミットを使用する新しい属性を作成できます。既存の命令的な実装がプリンシパルパーミットを使用している場合、これが当てはまるはずです。ただし、命令バージョンが他の何かを行う場合は、カスタム許可と対応する属性の両方を実装することを検討する必要がある場合があります。これが必要かどうかわからない場合は、おそらく現在の命令的なアプローチに関する詳細を共有できます...
質問の更新後...
実際には、PrincipalPermissionで「任意の」ロジックを使用することは可能ですが、複数のインスタンスの結合が必要です。これは、属性で作業することは特に実用的ではありません。これにより、カスタム属性を作成することがはるかに合理的になります。これは、次のようなものになる可能性があります。
[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class AnyRolePermissionAttribute : CodeAccessSecurityAttribute
{
public AnyRolePermissionAttribute(SecurityAction action)
: base(action)
{
}
public string Roles { get; set; }
public override IPermission CreatePermission()
{
IList<string> roles = (this.Roles ?? string.Empty).Split(',', ';')
.Select(s => s.Trim())
.Where(s => s.Length > 0)
.Distinct()
.ToList();
IPermission result;
if (roles.Count == 0)
{
result = new PrincipalPermission(null, null, true);
}
else
{
result = new PrincipalPermission(null, roles[0]);
for (int i = 1; i < roles.Count; i++)
{
result = result.Union(new PrincipalPermission(null, roles[i]));
}
}
return result;
}
}
残念ながら、セキュリティ属性で配列を使用することはできないため、ロールリストを文字列として表す必要があります。例えば:
[AnyRolePermission(SecurityAction.Demand, Roles = "Foo, Bar")]
設計時の連結を介して定数で使用できます。例えば:
[AnyRolePermission(SecurityAction.Demand, Roles = Roles.Administrator + ", " + Roles.Editor)]
カスタムロールプロバイダーに関しては、それを使用するのに適切な場所は、許可または属性ではなく、スレッドプリンシパルにあります。たとえば、現在GenericPrincipalを使用している場合は、カスタムロールプロバイダーを使用してターゲットIDの役割を取得するカスタムプリンシパルに置き換えることができます。
他のヒント
独自のcodeaccesssecurityattributeを導き出し、スレッドの周りにロジックを実装できます。currentprincipal(http://msdn.microsoft.com/en-us/library/system.security.permissions.codeccesssecurityattribute.aspx)。
基本的に、あなたは検証したいと思うでしょう allowedRoles.Any(r => Thread.CurrentPrincipal.IsInRole(r))