it-swarm.com.de

Vom Aktionsfilterattribut umleiten

Was ist der beste Weg, eine Umleitung in einer ActionFilterAttribute durchzuführen? Ich habe eine ActionFilterAttribute namens IsAuthenticatedAttributeFilter, die den Wert einer Sitzungsvariablen überprüft hat. Wenn die Variable "false" ist, möchte ich, dass die Anwendung zur Anmeldeseite umgeleitet wird. Ich würde es vorziehen, mit dem Routennamen SystemLogin umzuleiten, jedoch wäre jede Umleitungsmethode an dieser Stelle in Ordnung.

119
ryanzec

setze filterContext.Result

Mit dem Routennamen:

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

Sie können auch etwas tun:

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

Wenn Sie RedirectToAction verwenden möchten:

Sie können eine öffentliche RedirectToAction-Methode auf Ihrem Controller (vorzugsweise auf ihrem Basiscontroller) erstellen, die einfach die geschützte RedirectToAction von System.Web.Mvc.Controller aufruft. Das Hinzufügen dieser Methode ermöglicht einen öffentlichen Aufruf von yourRedirectToAction aus dem Filter.

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

Dann würde Ihr Filter ungefähr so ​​aussehen:

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

Alternativ zu einer Weiterleitung können Sie Folgendes verwenden, wenn Sie Ihren eigenen Code aufrufen:

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

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

Es ist keine reine Weiterleitung, liefert jedoch ein ähnliches Ergebnis ohne unnötigen Aufwand.

71
Syakur Rahman

Ich verwende MVC4 und verwendete den folgenden Ansatz, um einen benutzerdefinierten HTML-Bildschirm nach einer Autorisierungsverletzung umzuleiten.

AuthorizeAttribute erweitern, sagen Sie CutomAuthorizer Überschreiben Sie die OnAuthorization und HandleUnauthorizedRequest.

Registrieren Sie die CustomAuthorizer in der RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

nach dem Identifizieren des unAuthorized-ZugriffsanrufsHandleUnauthorizedRequestund Weiterleiten an die betroffene Controller-Aktion, wie unten gezeigt.


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

Es klingt, als ob Sie AuthorizeAttribute neu implementieren oder möglicherweise erweitern möchten. Wenn ja, sollten Sie sicherstellen, dass Sie das erben, und nicht ActionFilterAttribute, damit ASP.NET MVC mehr Arbeit für Sie erledigen kann.

Außerdem möchten Sie sicherstellen, dass Sie autorisieren, bevor Sie die eigentliche Arbeit in der Aktionsmethode ausführen. Andernfalls besteht der einzige Unterschied zwischen angemeldet und nicht darin, welche Seite nach Abschluss der Arbeit angezeigt wird.

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

Es gibt eine gute Frage mit einer Antwort mit mehr Details zu SO.

9
Tomas Aschan

Versuchen Sie das folgende Snippet, es sollte ziemlich klar sein:

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

Hier ist eine Lösung, die auch berücksichtigt, wenn Sie Ajax-Anfragen verwenden. 

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

Das funktioniert für mich (asp.net core 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

sie könnten Ihren Controller erben und ihn dann in Ihrem Aktionsfilter verwenden 

in Ihrer ActionFilterAttribute-Klasse: 

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

in Ihrem Basiscontroller: 

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

Cons. Dazu müssen alle Controller so geändert werden, dass sie von der Klasse "MyController" erben

0
msoliman