4

私たちの古いソフトウェア アーキテクチャは、役割ベースの検証を使用していました。次に、クレーム ベースの承認を使用します。実際のところ、ロールベースのテクノロジを使用していたとしても、主張をモデル化するものを常に使用していたと思います。

最下位レベルは特権です。特権は、「ユーザーを追加するユーザー サービスを呼び出す」または短い「UserService.Add」の場合があります。グループに権限を割り当てることができます。ユーザーはグループのメンバーになることができます。最終的に、グループ メンバーシップを通じて、ユーザーは特権のリストを持つことができます。

古いシステムでは、UserNamePasswordValidatorIAuthorizationPolicy、およびCodeAccessSecurityAttributeの組み合わせを使用して、サービス メソッドの上に記述された属性を持ち、サービス メソッドの呼び出し時に有効性がチェックされていました。ユーザーが必要な権限を持っていない場合、アクセスは拒否されます。うまくいきました。

[CompanyRoleRequired(SecurityAction.Demand, Role = "Common.Connect")]
[CompanyRoleRequired(SecurityAction.Demand, Role = "SomeServiceName.Save")]
public void Save(IEnumerable<Data> data)
{
  // code
}

ここで、クレーム ベースの承認を使用したいと思います。上記のモデルを維持して、以前の特権ごとにクレームを作成するか、またはその操作の有効な値を持つ各サービスのクレームを作成します。たとえば、"UserService.Add" の代わりにクレーム "UserService" を追加すると、以前の特権を持つユーザーは値 "Add" を持つクレームを取得できます。サービス開発者にも同様の簡単なアクセス チェックを提供したいので、サービス メソッドの上に必要なクレームに注釈を付けたいと考えています。Microsoft は、これに対してClaimsPrincipalPermissionAttributeを既に提供しています。

IAuthorizationPolicy を実装する代わりに、 ClaimsAuthorizationManager を実装しました。

質問 1)承認マネージャーが 2 回呼び出されます。1 回は SOAP の URL で、もう 1 回は自分の属性で。私はたくさんグーグルで検索しましたが、それは設計によるものと思われます。呼び出しを区別して自分の呼び出しだけをチェックするのに問題はありませんが、何かが見えなかったのかもしれません。URLを使用してsoap呼び出しで呼び出されず、属性に対してのみ呼び出されるオプションまたは簡単な方法はありますか?

質問 2)アクセス チェックは、プリンシパルがクレームを持っているかどうかをチェックする機能を提供します。明らかに、クレームにはタイプ/名前と値があります。属性がそのようなインターフェースを提供することを期待していたでしょう。ただし、属性はリソースと操作について知りたいと考えています。上書きする必要があるアクセスチェック機能は、リソースと操作もチェックする必要があります何故ですか?リソース/操作を AuthorizationManager のクレームにマップする必要がありますか? また、その必要性が見当たらない場合は、クレームの予想されるタイプと値をリソースと操作として属性に入れ、承認マネージャーでそれらを 1:1 でマップするだけでよいでしょうか? それとも、これを行うと重要なセキュリティ機能を逃してしまうのでしょうか?

4

2 に答える 2

6

Q1)残念ながらそうです。「自動」呼び出しと属性/.CheckAccessの両方が同じクレームタイプを使用しているため、2つを簡単に区別することはできません。私はここにそれについて書きました:http://leastprivilege.com/2011/04/30/what-i-dont-like-about-wifs-claims-based-authorization/

Q2)ここでコンセプトが欠けています。アイデアは、特定のクレームをチェックするのではなく、コードに「何をしているのか」という注釈を付けることです。ビジネスコードを作成する人は、通常、誰がそれを呼び出すことができるか(またはどのクレームが正確に必要か)を正確に知りません。authZポリシーに、顧客を追加しようとしていることだけを伝えます(例として)。許可マネージャーの仕事は、プリンシパルがそれを行うことを許可されているかどうかを把握することです(何らかの手段で)。関心事の分離。ここを参照してください:http://leastprivilege.com/2011/04/30/what-i-like-about-wifs-claims-based-authorization/

于 2013-03-11T10:56:30.350 に答える
1

これが役に立つかどうかはわかりませんが、ClaimsAuthorizationManager にはオーバーライド可能なメソッド (LoadCustomConfiguration) があり、これを使用して XML ファイルからポリシーをロードできます。そのポリシーは、リソースとアクションおよびロールの間のマッピングを許可するように設計されている場合があります。代わりに、次のようなコード内アクセス制御リストを作成しました。

public interface IAccessControlList
{
   List<CustomAccessRule> Rules { get; }
}

public class CustomAccessRule
{
    public string Operation { get; set; }
    public List<string> Roles { get; set; }

    public CustomAccessRule(string operation, params string[] roles)
    {
        Operation = operation;
        Roles = roles.ToList();
    }
}

私の要求承認マネージャーは次のようになります。

public class CustomClaimsAuthorizationManager : ClaimsAuthorizationManager
{
    private IAccessControlList _accessControlList;

    public CustomClaimsAuthorizationManager(IAccessControlList accessControlList)
    {
        _accessControlList = accessControlList;
    }

    public override bool CheckAccess(AuthorizationContext context)
    {
        string operation = context.Action.First().Value.Split('/').Last();
        CustomAccessRule rule = _accessControlList.Rules.FirstOrDefault(x => x.Operation == operation);
        if (rule == null) return true;
        if (context.Principal.Identities.First().IsInRoles(rule.Roles)) return true;
        throw new MessageSecurityException(string.Format("Username {0} does not have access to operation {1}.", context.Principal.Identities.First().Name, operation));
    }

}

以下は、1 つのサービスに対する 1 つのアクセス制御リストの実装例です。

public class SampleServiceACL : IAccessControlList
{
    public List<CustomAccessRule> Rules { get; private set; }

    public SampleServiceACL()
    {
        Rules = new List<CustomAccessRule>();
        Rules.Add(new CustomAccessRule("OpenAccount", "Manager", "Owner"));
        Rules.Add(new CustomAccessRule("CloseAccount", "Manager", "Owner"));
        Rules.Add(new CustomAccessRule("SendEmail", "User", "Manager", "Owner"));
    }
}

そして、次を使用して、これをサービス ホスト ベース レベルで適用しています。

    protected override void OnOpening()
    {
        base.OnOpening();

        IdentityConfiguration identityConfiguration = new IdentityConfiguration();
        identityConfiguration.SecurityTokenHandlers.Clear();
        identityConfiguration.ClaimsAuthorizationManager = new CustomClaimsAuthorizationManager(new SampleServiceACL());
        this.Credentials.IdentityConfiguration = identityConfiguration;

        ...
    }

その結果、私は属性をまったく使用していません。すべての承認ロジックは、ACL を介してクレーム承認マネージャーに集中化されています。

このアプローチが気に入らず、特定のクレームをチェックする属性を探している場合は、CodeAccessSecurityAttributeから派生させて、実際にそのロジックを実装できます。MS がすぐに提供するものは良いものですが、決してそれに固執する必要があるという意味ではありません。また、クレームをチェックするためのロジックは、ID の拡張として実装できます。つまり、次のようになります。

public static class IdentityExtensions
{
    public static bool IsInRoles(this ClaimsIdentity id, List<string> roles)
    {
        foreach (string role in roles)
            if (id.HasClaim(ClaimTypes.Role, role)) return true;
        return false;
    }
}

そのため、拡張機能、カスタム属性を作成し、属性で拡張機能を使用して検証ロジックを実行できます。

繰り返しますが、これは私がすでに行ったことです。探しているものではないかもしれませんが、これはカスタム ソリューションの 1 つのタイプです。

于 2013-03-11T05:42:02.060 に答える