it-swarm-eu.dev

Przekieruj z atrybutu filtru akcji

Jaki jest najlepszy sposób na przekierowanie w ActionFilterAttribute. Mam ActionFilterAttribute o nazwie IsAuthenticatedAttributeFilter i który sprawdził wartość zmiennej sesji. Jeśli zmienna ma wartość false, chcę, aby aplikacja przekierowywała do strony logowania. Wolałbym przekierować używając nazwy trasy SystemLogin, jednak każda metoda przekierowania w tym momencie byłaby w porządku.

119
ryanzec

Ustaw filtrContext.Result

Z nazwą trasy:

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

Możesz także zrobić coś takiego:

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

Jeśli chcesz użyć RedirectToAction:

Możesz stworzyć publiczną metodę RedirectToAction na kontrolerze (najlepiej na jej podstawowym kontrolerze), która po prostu wywołuje chronioną RedirectToAction z System.Web.Mvc.Controller. Dodanie tej metody pozwala na publiczne wywołanie yourRedirectToAction z filtru.

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

Wtedy twój filtr wyglądałby następująco:

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

Alternatywnie do przekierowania, jeśli wywołuje Twój własny kod, możesz użyć tego:

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

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

Nie jest to czyste przekierowanie, ale daje podobny wynik bez zbędnego narzutu.

71
Syakur Rahman

Używam MVC4, użyłem następującego podejścia do przekierowania niestandardowego ekranu html po naruszeniu autoryzacji.

Rozszerz AuthorizeAttribute powiedz CutomAuthorizer Nadpisz OnAuthorization i HandleUnauthorizedRequest

Zarejestruj CustomAuthorizer w RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

po identyfikacji wywołania unAuthorizedHandleUnauthorizedRequest i przekierowaniu do danej akcji kontrolera, jak pokazano poniżej.


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" }

                                         });

    }
}
11
user2834076

Brzmi to tak, jakbyś chciał ponownie wdrożyć, lub ewentualnie rozszerzyć, AuthorizeAttribute. Jeśli tak, powinieneś upewnić się, że odziedziczysz to, a nie ActionFilterAttribute, aby ASP.NET MVC mógł wykonać więcej pracy za Ciebie.

Ponadto, chcesz się upewnić, że autoryzujesz przed wykonujesz jakąkolwiek prawdziwą pracę w metodzie akcji - w przeciwnym razie jedyną różnicą między zalogowanym a nie będzie to, którą stronę widzisz po zakończeniu pracy.

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);
    }
}

Jest dobre pytanie z odpowiedzią więcej szczegółów tutaj na SO.

9
Tomas Aschan

Wypróbuj poniższy fragment, który powinien być dość jasny:

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);
  }
}
4
msoliman

Oto rozwiązanie, które bierze również pod uwagę, jeśli używasz żądań 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
Mike

To działa dla mnie (rdzeń 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
mortenma71

możesz odziedziczyć kontroler, a następnie użyć go w filtrze akcji 

wewnątrz klasy ActionFilterAttribute: 

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

wewnątrz kontrolera podstawowego: 

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

Cons. ma to na celu zmianę wszystkich kontrolerów, aby dziedziczyły z klasy „MyController”

0
msoliman