ServiceStack Serviceの実装内で標準のASP.NETセッションオブジェクトを使用するにはどうすればよいですか
-
26-10-2019 - |
質問
ServiceStackを始めたばかりで、テストケースとして、標準のASP.NETハンドラーを使用して構築された既存のサービスを作り直したいと考えています。私はそれを望んでいるようにすべて動作させることができましたが、ASP.NETセッションオブジェクトを使用する特定の側面を持っています。
IREQUIRESSESTIONSTATEをサービスインターフェイスに追加しようとしました。
public class SessionTestService : RestServiceBase<SessionTest>, IRequiresSessionState {
public override object OnPost(SessionTest request) {
// Here I want to use System.Web.HttpContext.Current.Session
}
}
問題は、セッションオブジェクトが常にnullであるため、それを機能させることができないようです。
私はたくさんのグーグルをしました、そして困惑しました https://github.com/mythz/servicestack/blob/master/tests/servicestack.webhost.integrationtests/services/secure.cs 同様ですが、これを行うコードを見つけることができません(これは私を驚かせます)。上記がうまくいかない理由を誰でも説明し、それを機能させるために私がする必要があることをアドバイスしてください。
ノート: 最終的に、私はおそらくこれをRedisに置き換えるか、サーバーサイドセッションの要件を削除しようとしますが、当面はASP.NETの実装を使用して、物事を機能させ、それ以上の作業を避けるために考えました。この時点で必要です。
解決
ServiceStack isessionを使用します
ServiceStackには新しいものがあります ISession
バックアップされたインターフェイス ICacheClient
それはあなたが同じ共有することを可能にします ISession
MVCコントローラー、ASP.NETベースページ、および同じCookie IDを共有するServicestackのWebサービスの間で、これらのWebフレームワーク間でデータを自由に共有できます。
注:isessionはaです クリーンな実装 これは、既存のASP.NETセッションを完全にバイパスします。 ServiceStackのMVC PowerPack で詳細に説明されています セッションwikiページ.
ServiceStackのセッション(Cache&JSON Serializer)を簡単に使用するには、コントローラーをから継承してもらいます ServiceStackController (MVCで)または PageBase (ASP.NETで)
ServiceStackに追加された新しい認証 /検証機能もあります。これについては、Wikiについて読むことができます。
ASP.NETセッションを使用します
本質的に ServiceStack 軽量のセットです ihttphandler's asp.netまたはhttplistenerホストのいずれかで実行されます。 IIS/ASP.NET(最も一般的な)でホストされている場合、通常のASP.NETリクエストのように機能します。
ServiceStackには、基礎となるASP.NETアプリケーションで構成されたキャッシュおよびセッションプロバイダーにアクセスまたは影響するものはありません。それを有効にする場合は、ASP.NETで通常どおりに構成する必要があります(つまり、ServiceStackの外側)を参照してください。
http://msdn.microsoft.com/en-us/library/ms178581.aspx
構成されたら、Singletonを介してServicestack Webサービス内のASP.NETセッションにアクセスできます。
HttpContext.Current.Session
または、基礎となるasp.net httprequestを介して:
var req = (HttpRequest)base.RequestContext.Get<IHttpRequest>().OriginalRequest;
var session = req.RequestContext.HttpContext.Session;
ただし、XML構成と デフォルトでパフォーマンスを低下させました, 、私はasp.netのセッションの使用を避け、代わりにクリーナーを使用することを選択することを好みます クライアントをキャッシュします ServiceStackに含まれています。
基本的にセッションの動作方法(ASP.NETを含む)は、 一意のID ブラウザセッションを一意に識別する応答に追加されます。これ ID ブラウザのセッションを表すサーバー上の一致する辞書/コレクションを指します。
iRequiressession リンクするインターフェイスはデフォルトで何もしません。これは、このリクエストを認証する必要があることをカスタムリクエストフィルターまたはベースWebサービスのいずれかに信号する方法です(つまり、ServiceStackに検証/認証ロジックを入力する必要があります。 )。
これが次のとおりです 基本的な認証実装 それは、Webサービスが安全であるかどうかを確認するように見えます。もしそうなら、彼らが認証されていることを確認してください。
これがそうです 別の認証実装 代わりに、ANでマークされたすべてのサービスを検証します 認証する 属性、および サービスの認証を有効にする方法 要求に属性を追加することにより、DTO。
ServiceStackの新しい認証モデル
上記の実装は、次のバージョンのServiceStackに含まれるMulti-Authプロバイダーモデルの一部です。これがそうです 参照例 アプリケーションで新しい認証モデルを登録および構成する方法を示します。
認証戦略
新しいAUTHモデルは、単にそれを使用して自分で同様の動作を実装できないため、完全にオプトインの利便性です。 フィルターを要求します またはで 基本クラス (オーバーライドすることによって onbeforeexecute)。実際、新しい認証サービスは、実際にはServicestackを組み込んでいません。実装全体がオプションに存在します ServiceStack.ServiceInterFacesプロジェクト カスタムリクエストフィルターを使用して実装しました。
ここに私が長年にわたって使用していたさまざまな認証戦略があります。
ANで認証が必要なサービスをマークします 属性. 。おそらく最も慣用的なC#の方法で、理想的です セッションID クッキーを介して渡されます。
特にWebコンテキストの外で、時にはより明示的なものを使用する iRequiresAuthentication インターフェイスは、認証に必要なユーザーへの強いタイプのアクセスとSessionIDを提供するため、優れています。
それを必要とする各サービスで認証するための1ライナーを使用することができます - アドホックベースで。認証を必要とするサービスが非常に少ない場合に適したアプローチ。
他のヒント
それは@mythzによる素晴らしい包括的な答えです。ただし、ASP.NETセッションにアクセスしようとするとき HttpContext.Current.Session
ServiceStack Webサービス内では、常に戻ります null
私のため。それは、ServiceStack内のhttphandlersが飾られていないためです IRequiresSessionState
インターフェイスなので、.NETフレームワークはセッションオブジェクトを提供しません。
これを回避するために、2つの新しいクラスを実装しました。どちらもデコレーターパターンを使用して必要なものを提供します。
まず、新しい IHttpHandler
セッション状態が必要です。ラップします IHttpHandler
ServiceStackによって提供され、通話を通過します...
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
生成の責任を委任します IHttpHandler
私たちの新しいで返されたハンドラーをラッピングする前に、ServiceStackに SessionHandlerDecorator
...
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);
}
}
それから、それはただ変化する問題です type
web.configのハンドラーの属性 SessionHttpHandlerFactory
それ以外の ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack
, 、そしてあなたのWebサービスは、ASP.NETセッションを彼らに利用できるようにする必要があります。
上記にもかかわらず、私は新しいことを完全に支持します ISession
ServiceStackが提供する実装。ただし、場合によっては、成熟した製品では、ASP.NETセッションのすべての使用を新しい実装に置き換えるには、あまりにも大きすぎるように思えます。したがって、この回避策!
上記の回答をありがとう@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);
}
}
}
ServiceStack 4.5+の時点では、HTTPhandlerもAsyncをサポートできます。そのようです:
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);
}
}
}