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.
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");
}
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.
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
-ZugriffsanrufsHandleUnauthorizedRequest
und 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" }
});
}
}
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.
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);
}
}
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);
}
}
}
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();
}
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