17

ServiceStackを使い始めたばかりで、テストケースとして、標準のASP.Netハンドラーを使用して構築された既存のサービスを作り直そうとしています。私はそれをすべて私が望むように動作させることができましたが、ASP.Netセッションオブジェクトを利用する特定の側面があります。

IRequiresSessionStateをサービスインターフェイスに追加してみました。

public class SessionTestService : RestServiceBase<SessionTest>, IRequiresSessionState {
    public override object OnPost(SessionTest request) {
        // Here I want to use System.Web.HttpContext.Current.Session
    }
}

問題は、Sessionオブジェクトが常にnullであるため、動作させることができないように見えることです。

私はたくさんのグーグルをして、https://github.com/mythz/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Services/Secure.csなどに戸惑いましたが、何も見つかりませんこれを行うサンプルコード(これは私を驚かせます)。上記が機能しない理由を誰かが説明し、それを機能させるために私が何をする必要があるかをアドバイスできますか?

注:最終的には、これをRedisに置き換えるか、サーバー側のセッション要件を削除しようとしますが、当面はASP.Net実装を使用して、動作を開始し、再動作を回避することにしました。この時点で必要以上のもの。

4

4 に答える 4

29

ServiceStackISessionの使用

ServiceStackには、 MVCコントローラー、ASP.NETベースページ、および同じCookie IDを共有するServiceStackのWebサービス間で同じものを共有できる新しいISessionインターフェイスがあり、これらのWebフレームワーク間でデータを自由に共有できます。ICacheClientISession

注:ISessionは、ServiceStackのMVC PowerPackで説明され、Sessions wikiページで詳細に説明されているように、ServiceStack独自のコンポーネントで既存のASP.NETセッションを完全にバイパスするクリーンな実装です。

ServiceStackのセッション(キャッシュとJSONシリアライザー)を簡単に利用するには、コントローラーをServiceStackController(MVCの場合)またはPageBase(ASP.NETの場合)から継承します。

ServiceStackには、新しい認証/検証機能も追加されています。これについては、wikiで読むことができます。

ASP.NETセッションの使用

基本的に、 ServiceStackは、ASP.NETまたはHttpListenerホストのいずれかで実行される軽量のIHttpHandlerのセットです。IIS / ASP.NET(最も一般的)でホストされている場合は、通常のASP.NET要求のように機能します。

ServiceStackには、基盤となるASP.NETアプリケーションで構成されたキャッシングプロバイダーとセッションプロバイダーにアクセスしたり、影響を与えたりするものはありません。有効にする場合は、ASP.NET(つまり、ServiceStackの外部)で通常どおりに構成する必要があります。以下を参照してください。

http://msdn.microsoft.com/en-us/library/ms178581.aspx

構成が完了すると、シングルトンを介してServiceStackWebサービス内のASP.NETセッションにアクセスできます。

HttpContext.Current.Session

または、基盤となるASP.NETHttpRequestを介して次のコマンドを実行します。

var req = (HttpRequest)base.RequestContext.Get<IHttpRequest>().OriginalRequest;
var session = req.RequestContext.HttpContext.Session;

XML構成への必須の依存とデフォルトでのパフォーマンスの低下のために、私はASP.NETのセッションの使用を避け、代わりにServiceStackに含まれているよりクリーンなキャッシュクライアントを使用することを選択します。

基本的に、セッションの動作(ASP.NETを含む)は、ブラウザーセッションを一意に識別する一意のIDを含むCookieが応答に追加されます。このIDは、ブラウザのセッションを表すサーバー上の一致するディクショナリ/コレクションを指します。

リンク先のIRequiresSessionインターフェースは、デフォルトでは何もしません。これは、カスタムリクエストフィルターまたはベースWebサービスに、このリクエストを認証する必要があることを通知する方法です(つまり、検証/認証ロジックを配置する必要がある2つの場所)。 ServiceStackで)。

これは、Webサービスが安全であるかどうかを確認し、安全である場合は認証されていることを確認する基本認証の実装です。

代わりに、 [Authenticate]属性でマークされたすべてのサービスを検証する別の認証実装と、リクエストDTOに属性を追加してサービスの認証を有効にする方法を次に示します。

ServiceStackの新しい認証モデル

上記の実装は、ServiceStackの次のバージョンに含まれるマルチ認証プロバイダーモデルの一部です。これは、アプリケーションで新しいAuthモデルを登録および構成する方法を示す参照例です。

認証戦略

新しいAuthモデルは、完全にオプトインの便利な機能です。これは、リクエストフィルターを使用して、または基本クラスで( OnBeforeExecuteをオーバーライドすることにより)自分で使用したり、同様の動作を実装したりすることができないためです。実際、新しいAuthサービスは実際にはServiceStack自体に組み込まれていません。実装全体は、オプションのServiceStack.ServiceInterfacesプロジェクトに存在し、カスタムリクエストフィルターを使用して実装されます。

これが私が何年にもわたって使用したさまざまな認証戦略です:

  • 認証が必要なサービスを[属性]でマークします。おそらく最も慣用的なC#の方法であり、セッションIDがCookieを介して渡される場合に理想的です。

  • 特にWebコンテキストの外部では、認証に必要なユーザーとSessionIdへの強い型のアクセスを提供するため、より明示的なIRequiresAuthenticationインターフェイスを使用する方がよい場合があります。

  • アドホックベースで、それを必要とする各サービスで認証するための1ライナーを持つことができます。認証を必要とするサービスが非常に少ない場合に適したアプローチ。

于 2011-12-05T02:10:12.110 に答える
19

これは、@mythzによる優れた包括的な回答です。HttpContext.Current.Sessionただし、 ServiceStack Webサービス内でASP.NETセッションにアクセスしようとすると、常に返さnullれます。これは、ServiceStack内のどのHttpHandlerもIRequiresSessionStateインターフェイスで装飾されていないため、.NETFrameworkがセッションオブジェクトを提供しないためです。

これを回避するために、2つの新しいクラスを実装しました。どちらもデコレータパターンを使用して、必要なものを提供します。

まず、IHttpHandlerセッション状態を必要とする新しい。ServiceStackによって提供されたものをラップし、IHttpHandler呼び出しを渡します...

public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState {
    private IHttpHandler Handler { get; set; }

    internal SessionHandlerDecorator(IHttpHandler handler) {
        this.Handler = handler;
    }

    public bool IsReusable {
        get { return Handler.IsReusable; }
    }

    public void ProcessRequest(HttpContext context) {
        Handler.ProcessRequest(context);
    }
}

次に、返されたハンドラーを新しい...でラップする前にIHttpHandlerFactory、を生成する責任をServiceStackに委任するnew。IHttpHandlerSessionHandlerDecorator

public class SessionHttpHandlerFactory : IHttpHandlerFactory {
    private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) {
        var handler = factory.GetHandler(context, requestType, url, pathTranslated);
        return handler == null ? null : new SessionHandlerDecorator(handler);
    }

    public void ReleaseHandler(IHttpHandler handler) {
        factory.ReleaseHandler(handler);
    }

}

次に、typeWeb.configのハンドラーの属性をSessionHttpHandlerFactoryではなくに変更するだけServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStackで、WebサービスでASP.NETセッションを利用できるようになります。

上記にもかかわらず、私はISessionServiceStackによって提供される新しい実装を完全に支持します。ただし、場合によっては、成熟した製品では、ASP.NETセッションのすべての使用を新しい実装に置き換えるのは大変な作業のように思われるため、この回避策があります。

于 2012-02-08T13:00:03.687 に答える
4

上記の回答をありがとう@Richard。新しいバージョンのサービススタックを実行していますが、HttpFactoryでServiceStackHttpFactoryが削除されました。持っている代わりに

private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();

あなたが持っている必要があります

private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();

このサービスの更新されたコードは次のとおりです

using ServiceStack;
using System.Web;
using System.Web.SessionState;

namespace MaryKay.eCommerce.Mappers.AMR.Host
{
public class SessionHttpHandlerFactory : IHttpHandlerFactory
{
    private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();
    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        var handler = Factory.GetHandler(context, requestType, url, pathTranslated);
        return handler == null ? null : new SessionHandlerDecorator(handler);
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
        Factory.ReleaseHandler(handler);
    }
}

public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState
{
    private IHttpHandler Handler { get; set; }

    internal SessionHandlerDecorator(IHttpHandler handler)
    {
        Handler = handler;
    }

    public bool IsReusable
    {
        get { return Handler.IsReusable; }
    }

    public void ProcessRequest(HttpContext context)
    {
        Handler.ProcessRequest(context);
    }
}
}
于 2015-12-15T17:28:35.537 に答える
2

ServiceStack 4.5以降では、HttpHandlerは非同期もサポートできます。そのようです:

namespace FboOne.Services.Host
{
  public class SessionHttpHandlerFactory : IHttpHandlerFactory
  {
    private static readonly HttpHandlerFactory Factory = new HttpHandlerFactory();

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
      var handler = Factory.GetHandler(context, requestType, url, pathTranslated);
      return handler == null ? null : new SessionHandlerDecorator((IHttpAsyncHandler)handler);
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
      Factory.ReleaseHandler(handler);
    }
  }

  public class SessionHandlerDecorator : IHttpAsyncHandler, IRequiresSessionState
  {
    private IHttpAsyncHandler Handler { get; set; }

    internal SessionHandlerDecorator(IHttpAsyncHandler handler)
    {
      Handler = handler;
    }

    public bool IsReusable
    {
      get { return Handler.IsReusable; }
    }

    public void ProcessRequest(HttpContext context)
    {
      Handler.ProcessRequest(context);
    }

    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
    {
      return Handler.BeginProcessRequest(context, cb, extraData);
    }

    public void EndProcessRequest(IAsyncResult result)
    {
      Handler.EndProcessRequest(result);
    }
  }
}
于 2016-11-13T12:25:14.530 に答える