Windows 認証を使用する ASP.Net MVC アプリケーションがあり、コントローラー アクションのセキュリティのためにグループ メンバーシップをチェックしています。
簡単に聞こえるかもしれませんが、私が経験している問題を解決できる他の質問は見つかりませんでした。
最初の試行: [承認]
古典的な方法は、コントローラー アクションにデータ アノテーション属性を単純に叩きつけAuthorize
て町に行くことです。
[Authorize(Roles = @"domain\groupName1")]
サイコロはありません。資格情報の入力を求められます。通常、これは Windows 認証構成に何か問題があることを意味しますが、セットアップは問題ありません: (1)HttpContext.User
はWindowsPrincipal
オブジェクトであり、(2) 別の既知のグループ名が機能することを確認しました。
2 回目の試行: IsInRole()
次のステップは、より古い方法で を使用することでした。また、一方が をIPrincipal.IsInRole()
返しfalse
、もう一方が を返しますtrue
。
var wp = (WindowsPrincipal)User;
// false
var inGroup1 = wp.IsInRole(@"domain\groupName1");
// true
var inGroup2 = wp.IsInRole(@"domain\groupName2");
困り果てたので、システム オタクに連絡して、すべてを再確認しました。ユーザーはグループのメンバーですか? はい。グループ名のつづりは正しいですか? はい。次のステップは、SID を取得することでした。
3 回目の試行: ID のグループ コレクションの検索
コントローラーWindowsIdentity
で、問題のあるグループの SID のグループ コレクションを調べます。
var wi = (WindowsIdentity)wp.Identity;
var group = wi.Groups.SingleOrDefault(g => g.Value == "group1-sidValue");
group
変数はオブジェクトSecurityIdentifier
です。null ではないため、この現在のユーザーが、[Authorize()]
またはの両方のIsInRole()
試行で確認に失敗したグループのメンバーであることが確実になります。
4 回目の試行: DirectoryServices.AccountManagement
この時点で、私は夢中になり、AccountManagement API への参照を追加します。GroupPrincipal
名前と SIDの両方でドメイン コンテキストを検索します。
var pc = new PrincipalContext(ContextType.Domain, "domain");
var gp1byName = GroupPrincipal.FindByIdentity(pc, "groupName1")
var gp1bySid = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, "group1-sidValue");
両方のグループ プリンシパル変数は同じオブジェクトで熟しており、監視変数を使用して、プリンシパルのMembers
コレクションに現在のonUserPrincipal
と同じ SID を持つオブジェクトが含まれていることを確認しました。WindowsPrincipal
HttpContext
質問:
ここで一体何を見逃したのですか?ユーザーがこの特定のグループの有効なメンバーであることがオブジェクトの調査によって明白である場合、両方の役割チェック方法が失敗するのはなぜですか?
この時点で、1 つのグループが正常にチェックされ、もう 1 つのグループがチェックされないという事実は、最も奇妙に思えます。