アクションフィルター属性からリダイレクト


139

でリダイレクトを行うための最良の方法は何ですかActionFilterAttribute。私はActionFilterAttribute呼び出されIsAuthenticatedAttributeFilter、セッション変数の値をチェックしました。変数がfalseの場合、アプリケーションがログインページにリダイレクトされるようにします。ルート名を使用してリダイレクトしSystemLoginたいのですが、この時点でのリダイレクト方法は問題ありません。


回答:


186

filterContext.Resultを設定します。

ルート名:

filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);

次のようなこともできます:

filterContext.Result = new ViewResult
{
    ViewName = SharedViews.SessionLost,
    ViewData = filterContext.Controller.ViewData
};

使用したい場合RedirectToAction

RedirectToActionコントローラーから(できればそのベースコントローラーで)パブリックメソッドを作成して、単にRedirectToActionから保護されたを呼び出すことができますSystem.Web.Mvc.Controller。このメソッドを追加する RedirectToActionと、フィルターからへのパブリックコールが可能になります。

public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
    return base.RedirectToAction(action, controller);
}

すると、フィルターは次のようになります。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}

8
これは機能しますが、利用可能なRedirectToActionメソッドがあるべきではありませんか?
ベン・ミルズ

@BenMillsには​​ありprotectedますが、フィルタからはアクセスできません。
ジェームズ

10
私の質問は、なぜマイクロソフトがこのフィルターを作成することを決めたのprotectedですか?RedirectToActionなぜ最初からそれがカプセル化されたのか理解せずに、このアクセシビリティを再定義することは非常に汚い感じです。
Matthew Marlin

2
@MatthewMarlin-アクションにリダイレクトするための正しい答えについては、Syakurの答えを参照してください。アクションフィルターから直接コントローラーを呼び出すことはできません。つまり、密結合の定義です。
NightOwl888 2016

1
@Akbari属性のOrderプロパティを設定してみましたか?また、FilterScopeは実行順序に影響を与えます。
CRice

79

リダイレクトの代わりに、独自のコードを呼び出す場合は、次のように使用できます。

actionContext.Result = new RedirectToRouteResult(
    new RouteValueDictionary(new { controller = "Home", action = "Error" })
);

actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);

純粋なリダイレクトではありませんが、不必要なオーバーヘッドなしで同様の結果が得られます。


あなたは私を助けました。ありがとう!
Edgar Salazar

25
actionContext.Result.ExecuteResultアクションフィルター内から呼び出してはいけないことに注意してください。MVCはアクションフィルターの実行後に自動的に呼び出します(ただしactionContext.Resultnullでない場合)。
NightOwl888 2016

12

私はMVC4を使用していますが、次のアプローチを使用して、認証違反時にカスタムHTML画面をリダイレクトしました。

拡張AuthorizeAttribute言うCutomAuthorizer 上書きOnAuthorizationし、HandleUnauthorizedRequest

登録CustomAuthorizerRegisterGlobalFilters

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

以下に示すように、unAuthorizedアクセス呼び出しを識別HandleUnauthorizedRequestし、関係するコントローラーアクションにリダイレクトします。


public class CustomAuthorizer : AuthorizeAttribute
{

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool isAuthorized = IsAuthorized(filterContext); // check authorization
        base.OnAuthorization(filterContext);
        if (!isAuthorized && !filterContext.ActionDescriptor.ActionName.Equals("Unauthorized", StringComparison.InvariantCultureIgnoreCase)
            && !filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("LogOn", StringComparison.InvariantCultureIgnoreCase))
        {

            HandleUnauthorizedRequest(filterContext);

        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result =
       new RedirectToRouteResult(
           new RouteValueDictionary{{ "controller", "LogOn" },
                                          { "action", "Unauthorized" }

                                         });

    }
}

9

再実装したい、あるいは拡張したいようですAuthorizeAttribute。その場合、ActionFilterAttributeASP.NET MVCがより多くの作業を行えるようにするために、継承ではなく継承していることを確認する必要があります。

また、アクションメソッドで実際の作業を行う前に承認を確認する必要があります。それ以外の場合は、ログイン時とそうでない場合の唯一の違いは、作業が完了したときに表示されるページです。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Do whatever checking you need here

        // If you want the base check as well (against users/roles) call
        base.OnAuthorization(filterContext);
    }
}

SOの詳細については、回答とともに良い質問があります


5

次のスニペットを試してみてください、それはかなりはっきりしているはずです:

public class AuthorizeActionFilterAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(FilterExecutingContext filterContext)
  {
    HttpSessionStateBase session = filterContext.HttpContext.Session;
    Controller controller = filterContext.Controller as Controller;

    if (controller != null)
    {
      if (session["Login"] == null)
      {
        filterContext.Cancel = true;
        controller.HttpContext.Response.Redirect("./Login");
      }
    }

    base.OnActionExecuting(filterContext);
  }
}

これは私にとってはうまくいきました、ユーザーがクエリ文字列の値を変更しようとして、ActionFilterAttributeを使用して許可されていないメッセージページにリダイレクトするよりも許可されていないデータにアクセスしようとした場合、クエリ文字列の値を確認する必要がありました。
2013年

3

これは、Ajaxリクエストを使用している場合にも考慮されるソリューションです。

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace YourNamespace{        
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeCustom : ActionFilterAttribute {
        public override void OnActionExecuting(ActionExecutingContext context) {
            if (YourAuthorizationCheckGoesHere) {               
                string area = "";// leave empty if not using area's
                string controller = "ControllerName";
                string action = "ActionName";
                var urlHelper = new UrlHelper(context.RequestContext);                  
                if (context.HttpContext.Request.IsAjaxRequest()){ // Check if Ajax
                    if(area == string.Empty)
                        context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(controller, action))}');</script>");
                    else
                        context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(area, controller, action))}');</script>");
                } else   // Non Ajax Request                      
                    context.Result = new RedirectToRouteResult(new RouteValueDictionary( new{ area, controller, action }));             
            }
            base.OnActionExecuting(context);
        }
    }
}

1

これは私のために動作します(asp.netコア2.1)

using JustRide.Web.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace MyProject.Web.Filters
{
    public class IsAuthenticatedAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.HttpContext.User.Identity.IsAuthenticated)
                context.Result = new RedirectToActionResult(nameof(AccountController.Index), "Account", null);
        }
    }
}



[AllowAnonymous, IsAuthenticated]
public IActionResult Index()
{
    return View();
}

0

コントローラを継承して、アクションフィルタ内で使用することができます

ActionFilterAttributeクラス内:

   if( filterContext.Controller is MyController )
      if(filterContext.HttpContext.Session["login"] == null)
           (filterContext.Controller as MyController).RedirectToAction("Login");

ベースコントローラーの内部:

public class MyController : Controller 
{
    public void  RedirectToAction(string actionName) { 
        base.RedirectToAction(actionName); 
    }
}

短所 これは、すべてのコントローラーを「MyController」クラスから継承するように変更することです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.