在ActionFilterAttribute
中进行重定向的最佳方法是什么。我有一个名为ActionFilterAttribute
的{{1}},它检查了会话变量的值。如果变量为false,我希望应用程序重定向到登录页面。我更倾向于使用路由名称IsAuthenticatedAttributeFilter
重定向,但此时任何重定向方法都可以。
答案 0 :(得分:166)
设置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");
}
答案 1 :(得分:70)
除了重定向,如果它正在调用您自己的代码,您可以使用:
actionContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { controller = "Home", action = "Error" })
);
actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);
它不是纯粹的重定向,而是提供类似的结果而没有不必要的开销。
答案 2 :(得分:12)
我正在使用MVC4,我使用以下方法在授权违规时重定向自定义html屏幕。
延长AuthorizeAttribute
说CutomAuthorizer
覆盖OnAuthorization
和HandleUnauthorizedRequest
在CustomAuthorizer
注册RegisterGlobalFilters
。
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" }
});
}
}
答案 3 :(得分:9)
听起来你想要重新实现,或者可能扩展AuthorizeAttribute
。如果是这样,你应该确保继承它,而不是ActionFilterAttribute
,以便让ASP.NET MVC为你做更多的工作。
另外,你想确保在之前授权你在action方法中做任何实际的工作 - 否则,登录和不登录之间的唯一区别将是你看到的页面工作已经完成。
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);
}
}
答案 4 :(得分: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);
}
}
答案 5 :(得分:1)
这是一个解决方案,如果您正在使用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);
}
}
}
答案 6 :(得分: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”类
答案 7 :(得分:0)
这对我有用(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();
}