Redirect From Action Filter Attribute

2019-01-03 08:57发布

What is the best way to do a redirect in an ActionFilterAttribute. I have an ActionFilterAttribute called IsAuthenticatedAttributeFilter and that checked the value of a session variable. If the variable is false, I want the application to redirect to the login page. I would prefer to redirect using the route name SystemLogin however any redirect method at this point would be fine.

8条回答
迷人小祖宗
2楼-- · 2019-01-03 08:59

This works for me (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();
}
查看更多
We Are One
3楼-- · 2019-01-03 09:07

It sounds like you want to re-implement, or possibly extend, AuthorizeAttribute. If so, you should make sure that you inherit that, and not ActionFilterAttribute, in order to let ASP.NET MVC do more of the work for you.

Also, you want to make sure that you authorize before you do any of the real work in the action method - otherwise, the only difference between logged in and not will be what page you see when the work is done.

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

There is a good question with an answer with more details here on SO.

查看更多
家丑人穷心不美
4楼-- · 2019-01-03 09:10

Try the following snippet, it should be pretty clear:

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楼-- · 2019-01-03 09:15

Here is a solution that also takes in account if you are using Ajax requests.

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楼-- · 2019-01-03 09:21

Set filterContext.Result

With the route name:

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

You can also do something like:

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

If you want to use RedirectToAction:

You could make a public RedirectToAction method on your controller (preferably on its base controller) that simply calls the protected RedirectToAction from System.Web.Mvc.Controller. Adding this method allows for a public call to your RedirectToAction from the filter.

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

Then your filter would look something like:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}
查看更多
Explosion°爆炸
7楼-- · 2019-01-03 09:21

you could inherit your controller then use it inside your action filter

inside your ActionFilterAttribute class:

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

inside your base controller:

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

Cons. of this is to change all controllers to inherit from "MyController" class

查看更多
登录 后发表回答