2013-04-15 11 views
6

私はテナントモデルごとに1つのデータベースを使用してマルチテナントアプリケーションを作成しています。私はブラウザに送信された各ページには、Site.Masterマルチテナントアプリケーションでは、1人のユーザーが多くのテナントアカウントにアクセスできますか?

<%= Html.Hidden("TenantId") %> 

しかし、どのような要求で現在のTenantIdを含み(限り、そのテナントがそれらにアクセス権を与えているように)複数のテナントにアクセスするために

を各ユーザーアカウントを許可していますブラウザから(ボタンを送信、AJAX GETまたはAJAX POST)、このTenantIdは、実際にユーザーの現在のTenantIdと一致するかどうかチェックされません。ユーザがTenantId = 1つのタブを開いた場合

すぐ、その後TenantId = 2の別のタブに別のテナントに接続し、その後、最初のタブに切り替わり、それがテナントからのデータへのアクセスを有する2

これを解決するにはどうすればよいですか?私は、既存のActionResultとするJsonResult多数の方法があり、それが

重複努力が大量になるので、私はそれらの一つ一つを通過し、

if (request.TenantId != user.CurrentTenantId) return false 

を追加したくない私は変更することはできTenantIdの値を常に読み取るベースコントローラ?それは提出されたリクエスト(ActionResult)で動作する可能性がありますが、AJAXリクエストはどうですか?

私はすべての単一の既存のAJAX方法を変更せずにするJsonResultアクションの内部ページのTenantIdを確認することができますどのように(それらの多くがありますか)?

答えて

2

Global.asax.csファイルのApplication_Requestイベントで確認できます。必要なものがMVCモデルバインディングを介して設定されている場合は、カスタムActionFilterを作成して確認し、GlobalFilterを介してすべてのアクションに登録してください。

-1

コントローラレベルでフィルタを適用し、送信中のテナントントを確認できます。コントローラレベルのフィルタは、アクションフィルタよりも難しくありません。私のプロジェクトでは、同様の方法で承認を確認する必要がありましたが、私は非常に特別なニーズがあったので、コントローラクラスをオーバーロードしてから、自分のコントローラクラスから継承しました。

テナントIDはどこにクライアント側に保存しますか?これを行うには、セッションオブジェクトを使用する必要があります。あなたがあなた自身のフィルターを書くことができ

+0

私はすでに、すべてのコントローラが継承するベースコントローラクラスを持っています。これを使用してフィルタを追加するにはどうすればよいですか?そして確かにそれはActionResultメソッド(フォームのフィールドのどれかをチェックできるのでフォームのサブミットにあります)にのみ影響しますが、JsonResultのものではありません(これらはAJAXサブミットであり、フォームコレクションのオブジェクト) –

0

:もちろん

How do I get certain code to execute before every single controller action in ASP.NET MVC 2? Executing code before any action

をあなたが質問のための準備ができて答えはありません。あなた自身のロジックを書く必要があり、tenantIdを処理する方法。たとえば、各アクションで、現在のセッションテナントIDがリダイレクトを行うのと同じではないかどうかを確認します。または、クッキーに入れ、idが等しいかどうかを毎回チェックします。それはあなた次第です。私の視点から見ると、クッキーはもっと好きです。しかし、それはトラフィックを食べる。

0

私が正しく理解していれば、それぞれ異なるテナントを持つ2つのタブを同時に開くことができます。各ページには、各テナントに関連するデータが表示されます。

だから、テナントは、各ブラウザタブに固有であるとして廃棄されるクッキーやセッションのニーズを含む溶液を意味します。

Cyril Guptaの提案に対するあなたの答えを読んで、各ページの隠されたテナントIDがAJAXリクエストごとに提出されないことを理解しています。 もちろん、1つの解決策は、アプリケーションを変更して、これが常にすべてのAJAX要求で当てはまることを確認することです。 それ以外の場合は、テナントIDが常に存在するとは限りませんので、リクエストパラメータに基づいてグローバルフィルタも破棄されます。

私は、tenantIdを保持するURLにセグメントを追加することをお勧めします。 (あなたは多くの異なったルートを持っている場合は、ルートの衝突を避けるために非常に注意する必要があるだろう)次のルートのようなもので、デフォルトルートを交換する例を示します。

routes.MapRoute(
      name: "Default", 
      url: "{tenant}/{controller}/{action}/{id}", 
      defaults: new { tenant = "defaultTenant", controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 

あなたは確認することができます。この方法でテナント常にますそれぞれの要求に応じて提出することができます。また、適切なデータをそれぞれ表示するテナントの異なる2つのタブを持つこともできます。

ルートセグメントの値を回復する方法にはさまざまなオプションがあります。

バインディングでは、アクションメソッドの "tenant"という名前のパラメータ、またはアクションメソッドのパラメータであるモデルクラスの "tenant"という名前のパラメータに自動的に値が設定されます。public ActionResult Foo(FooModelモデル、文字列テナント) { //テナントとmodel.tenantの両方にURLセグメントの値が含まれます 戻り値View(); }

また(RouteDataがフィルタメソッドのパラメータとして受信ActionExecutingContextActionExecutedContextクラスのプロパティである)ルートパラメータの値にアクセスフィルタを書き、いくつかのロジックを実行することができました。フィルタは、あなたのアプリケーションまたはお使いのベースのコントローラにグローバルフィルタとして設定されます:

public class FooFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var tenant = filterContext.RouteData.Values["tenant"] 
     //do whatever you need to do before executing the action, based on the tenant 
    } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var tenant = filterContext.RouteData.Values["tenant"] 
     //do whatever you need to do after executing the action, based on the tenant 
    } 
} 

最後のオプションは、直接お使いのベースのコントローラクラスにRouteDataパラメータにアクセスすることです。 (RouteDataはベースMVC Controllerクラスのプロパティです)

URL生成にHtmlとAjaxヘルパーを使用している限り、URLのテナントセグメントはリンク内で維持されます。しかし、ハードコードされたURLを持つAJAX呼び出しを直接送信するjqueryコードがある場合、新しいURLセグメントが考慮されるようにそのコードを更新する必要があります。

最後に、tenantIdの値が整数のようにユーザーフレンドリーではない場合、テナントごとに一意の名前を付け、URLの名前を使用することができます。アプリケーションに必要な整数値にマップするロジックを追加します。

+0

申し訳ありませんが、明確にするために:私は両方のタブが同時に動作する必要はありません。ユーザーが第2テナントアカウントにログインしているため、最初のタブがそれ以上のデータをロードすることを拒否するだけでよい。また、テナントIDをURLに入れたくないのですが、それが役立つ場合は、ページのフォームコレクションで利用できるようにしています。 –

+0

@JKの場合、同様のアプローチをとることができますが、要求からテナントIDを回復することができます(これは基本的に他のものがすでに提案しています)。問題は、すべてのAJAXリクエストでテナントIDが送信されるようにする必要があることです –

関連する問題