1

スコープと WIF に関してかなり複雑な問題が発生しています。すべてのアプリケーション セキュリティを処理するサービス クラス (SecurityService) があります。クレームの作成、ClaimsPrincipal の設定などを行います。Ninject とバインドされています。

現在、WIF には ClaimsAuthorizationManager クラスと ClaimsAuthenticationManager クラスがあり、必要に応じてキャッシュされたプリンシパルを使用する方法があります。これら 2 つのクラスはそれぞれ SecurityService を使用し、プリンシパルはそのクラスで作成および格納されます。

プリンシパルがキャッシュされると、SecurityService がそのキャッシュされたバージョンを受け取り、それをインスタンス変数として使用できるように、コードをセットアップしました。サービスは InRequestScope() にバインドされています。WIF クラスにはパラメーターのないコンストラクターが必要なので、Ninject DependencyResolver.Current.GetService<>() メソッドを使用します。

問題は、2 番目のコピーを作成しているように見えるか、WIF 作業が発生しているときに RequestScope が開始されていないことです。SecurityService は、コード内のオブジェクトに割り当てられたときに、クレームが割り当てられたプリンシパルを持っていません。

認証マネージャーの例を次に示します。

public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager
{
    private readonly SecurityService _MySecurityService;

    public HeritageClaimsAuthenticationManager(SecurityService heritageSecurityService)
    {
        _MySecurityService = heritageSecurityService;
    }

    public MyClaimsAuthenticationManager()
        : this(System.Web.Mvc.DependencyResolver.Current.GetService(typeof(SecurityService)) as SecurityService)
    {
    }

    /// <summary>
    /// Provides the framework extension to transform an incoming principal into an application specific principal.
    /// </summary>
    /// <param name="resourceName"></param>
    /// <param name="incomingPrincipal"></param>
    /// <returns>An Application specific ClaimsPrincipal</returns>
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
        {
            return TransformPrincipal(incomingPrincipal);
        }
        //Something is wrong with the incoming principal. Let the base implementation handle it.
        return base.Authenticate(resourceName, incomingPrincipal);
    }

    /// <summary>
    /// Given an existing claims principal, transform it to fit the needs of the current application,
    /// then store it in session.
    /// </summary>
    /// <param name="incomingPrincipal"></param>
    /// <returns></returns>
    public ClaimsPrincipal TransformPrincipal(ClaimsPrincipal incomingPrincipal)
    {
        _MySecurityService.CreateHeritagePrincipal(incomingPrincipal);
        ...
        return _MySecurityService.Principal;
    }
}

WIF のコンストラクター要件により、DependencyResolver を使用します。この時点で、_MySecurityService.Principal 価値があります。ただし、リクエスト ライフ サイクルの後半で、Ninject はプリンシパルを持たないサービスを返します。

また、IHttpModule を使用して WindowsPrincipal をインターセプトし、認証マネージャーを使用してhttp://leastprivilege.com/2012/04/04/identity-in-net-4-5part-2-claims-transformation-inに従ってクレームを変換します-asp-net-beta-1/ .

それもうまく機能しているようです。バインディングを InRequestScope() から InSingletonScope() に変更すると、すべてがうまく機能します。もちろん、これは複数のユーザーでは機能しません。また、HttpContext.User を見ると、ClaimsPrincipal が含まれています。

バインディングは次のとおりです。

Bind<ISecurityService>()
    .ToMethod<MySecurityService>(
        m => new MySecurityService(
                 new Collection<ISecurityClaimProvider>()
                     {
                         new UserClaimDao(new MyDbContext("MyDbContext"))
                     }
                 )).InRequestScope();

DAO がサービスのアプリケーション クレームを戻す場所。_MySecurityService.CreateHeritagePrincipal(incomingPrincipal)

要約すると、すべてが正しく配線されているようです。WIF クラスの Ninject 操作は、リクエストの範囲外で行われているようです。

何か不足していますか?範囲については正しいですか?もしそうなら、それを回避する方法はありますか?そうでない場合、このシナリオにどのように対処していますか?

実際、WIF クラスが動作する前に Application_BeginRequest が発生することを確認したので、完全に途方に暮れています。

4

1 に答える 1

1

ありがたいことに、私は自分の問題を理解し、期待どおりに動作するようになりました。2 つの主な問題がありました。まず、質問を投稿した後、すぐに気づきました。Bindメソッドがクラスを「新しくする」ため、上記のステートメントは常に新しいインスタンスを生成します。適切な構文は次のとおりです。

Bind<ISecurityService>().To<SecurityService>()
    .InRequestScope()
    .WithConstructorArgument("claimProviders",
        ctx => new Collection<ISecurityClaimProvider>
            {
                new UserClaimSecurityDao(
                new DbContext("MyDbContext"))
            });

必要でしたが、これで問題は解決しませんでした。Dominick Baier による上記の参照記事で提供されている HTTPModule を使用しました。「認証後」イベントにロジックを配置し、「リクエスト状態の取得」イベントに移動する必要がありました。InRequestScopeサービスが の外部でインスタンス化され、そのスコープ内で一度再インスタンス化されていることを観察したことは正しかったです。

影響があることを確認していない3番目の変更を行いました。NinjectWebCommon はHttpModules動的にインスタンス化するため、web.config で設定した 2 つがそれらの後に読み込まれたかどうかを確認できませんでした。私は web.config から私のものを削除し、NinjectWebCommon に追加したので、これが Start() メソッドになりました。

public static void Start()
{
    DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
    DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
    DynamicModuleUtility.RegisterModule(typeof(SessionAuthenticationModule));
    DynamicModuleUtility.RegisterModule(typeof(ClaimsTransformationHttpModule));
    Boot.Initialize(CreateKernel);
}

私の苦しみが誰かの役に立てば幸いです。

これは、Web.ConfigNinjectWebCommon.cs の両方でこれらの HttpModules を定義した場合にのみ機能することがわかりました。

于 2013-07-22T16:22:29.320 に答える