1

リクエストごとにCommunityPrincipal(IPrincipalインターフェイスを実装)オブジェクトを作成するHttpModuleがあります。リクエストごとにオブジェクトを保存したいので、キャストや再作成をしなくても、必要なときにいつでもオブジェクトを取得できます。

基本的に、FormsAuthenticationModuleの動作を模倣したいと思います。リクエストごとに、HttpContext.UserプロパティにIPrincipalインターフェイスを実装するオブジェクトを割り当てます。

どういうわけか、etcを呼び出せるようにしたいと思います。HttpContext.MySpecialUser(またはMySpecialContext.MySpecialUser-静的クラスを作成できます)は、オブジェクト(特定のタイプ)を返します。

拡張メソッドを使用することはできますが、リクエスト中にアクセスできるようにオブジェクトを保存する方法がわかりません。

これはどのように達成できますか?

特定のタイプとして保存したいことに注意してください(CommunityPrincipal-オブジェクトとしてだけではありません)。もちろん、処理中の現在のリクエストでのみ使用可能であり、他のすべてのスレッド/リクエストと共有されてはなりません。

現在、CommunityPrincipalオブジェクトをHttpModuleのHttpContext.Userに割り当てていますが、IPrincipalインターフェイスで定義されていないCommunityPrincipalオブジェクトのプロパティを使用する必要があるたびに、キャストを実行する必要があります。

4

3 に答える 3

1

データをスレッド自体に結合しないようにすることをお勧めします。asp.netが現在または将来どのようにスレッドを使用するかを制御することはできません。

データはリクエストコンテキストに非常に関連しているため、コンテキストとともに定義、有効化、および終了する必要があります。これは適切な場所であり、HttpModuleでオブジェクトをインスタンス化することも適切です。

キャストは実際にはそれほど問題にはならないはずですが、それを避けたい場合は、このためのHttpContextの拡張メソッドを強くお勧めします...これはまさに拡張メソッドが処理するように設計されている状況です。 。

これが私がそれを実装する方法です:

拡張メソッドを配置する静的クラスを作成します。

public static class ContextExtensions
{
    public static CommunityPrinciple GetCommunityPrinciple(this HttpContext context)
    {
        if(HttpContext.Current.Items["CommunityPrinciple"] != null)
        {
            return HttpContext.Current.Items["CommunityPrinciple"] as CommunityPrinciple;
        }
    }
}

HttpModuleで、プリンシパルを次のようなコンテキストアイテムコレクションに配置します。

HttpContext.Current.Items.Add("CommunityPrincipal", MyCommunityPrincipal); 

これにより、通常のコンテキストのユーザープロパティが自然な状態に保たれるため、サードパーティのコード、フレームワークコード、およびその他の記述が、そこでストローされた通常のIPrincipalを改ざんするリスクがなくなります。インスタンスは、それが有効であるユーザーの要求中にのみ存在します。そして何よりも、このメソッドは、通常のHttpContextメンバーであるかのようにコーディングでき、キャストは必要ありません。

于 2009-10-07T05:01:31.397 に答える
0

オブジェクトはすでにHttpContext.Userプロパティに格納されているため、目標を達成するために本当に必要なのは、目標を達成する静的メソッドだけです。

  public static class MySpecialContext
  {
    public static CommunityPrinciple Community
    {
        get
        {
           return (CommunityPrinciple)HttpContext.Current.User;
        }
    }
  }

これで、CommunityPrincipleを次のように取得できます。-

  var x = MySpecialContext.Community;

ただし、回避するのは大変な努力のようです。-

  var x = (CommunityPrinciple)Context.User;

別の方法は、HttpContextのExtensionメソッドです:-

  public static class HttpContextExtensions
  {
    public static CommunityPrinciple GetCommunity(this HttpContext o)
    {
      return (CommunityPrinciple)o.User;
    }
  }

それを使用してください:-

  var x = Context.GetCommunity();

これはかなり整頓されていますが、必要な各ファイルの使用リストで拡張クラスが定義されている名前空間を含めることを忘れないでください。

編集

今のところ、上記のように呼び出されたコード内で実行されたキャストでさえまだ受け入れられないという本当に正当な理由があると仮定しましょう(ところで、私はどのような状況があなたをこの結論に導くのかを理解することに本当に興味があります)。

さらに別の選択肢はThreadStaticフィールドです:-

  public class MyModule : IHttpModule
  {
    [ThreadStatic]
    private static CommunityPrinciple _threadCommunity;

    public static CommunityPrinciple Community
    {
        get
        {
           return _threadCommunity;
        }
    }
    // Place here your original module code but instead of (or as well as) assigning
    // the Context.User store in _threadCommunity.
    // Also at the appropriate point in the request lifecyle null the _threadCommunity

  }

[ThreadStatic]で装飾されたフィールドには、スレッドごとに1つのストレージインスタンスがあります。したがって、複数のスレッドが_threadCommunityを変更および読み取ることができますが、それぞれがフィールドの特定のインスタンスで動作します。

于 2009-08-02T08:16:18.203 に答える
0

カスタムプリンシパルをContext.Userに割り当てるのは正しいです。うまくいけば、Application_AuthenticateRequestでそれを行っています。

あなたの質問に来て、あなたはASPXページからのみユーザーオブジェクトにアクセスしますか?もしそうなら、あなたはあなたのためにキャストを含むカスタムベースページを実装することができます。

public class CommunityBasePage : Page
{
    new CommunityPrincipal User
    {
        get { return base.User as CommunityPrincipal; }
    }
}

次に、ページを継承するCommunityBasePageようにすると、からすべてのプロパティにアクセスできるようになりますthis.User

于 2009-10-08T10:17:07.793 に答える