Chuyển hướng từ thuộc tính bộ lọc hành động


139

Cách tốt nhất để làm một chuyển hướng trong một ActionFilterAttribute. Tôi có một cuộc ActionFilterAttributegọi IsAuthenticatedAttributeFiltervà đã kiểm tra giá trị của biến phiên. Nếu biến là sai, tôi muốn ứng dụng chuyển hướng đến trang đăng nhập. Tôi muốn chuyển hướng sử dụng tên tuyến SystemLogintuy nhiên mọi phương thức chuyển hướng tại thời điểm này đều ổn.


Câu trả lời:


186

Đặt bộ lọcContext.Result

Với tên tuyến đường:

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

Bạn cũng có thể làm một cái gì đó như:

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

Nếu bạn muốn sử dụng RedirectToAction:

Bạn có thể tạo một RedirectToActionphương thức công khai trên bộ điều khiển của mình ( tốt nhất là trên bộ điều khiển cơ sở của nó ) mà chỉ cần gọi bảo vệ RedirectToActiontừ System.Web.Mvc.Controller. Thêm phương thức này cho phép thực hiện cuộc gọi công khai tới bạn RedirectToAction từ bộ lọc.

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

Sau đó, bộ lọc của bạn sẽ trông giống như:

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

8
Điều này hoạt động, nhưng không nên có sẵn một phương thức RedirectToAction?
Ben Mills

@BenMills, tuy nhiên, protectedvì vậy bạn sẽ không có quyền truy cập từ bộ lọc.
James

10
Câu hỏi của tôi bây giờ là tại sao Microsoft quyết định tạo bộ lọc này protectedphải có một số giải thích hợp lý? Tôi cảm thấy rất bẩn khi xác định lại khả năng tiếp cận này RedirectToActionmà không hiểu tại sao nó được gói gọn ở nơi đầu tiên.
Matthew Marlin

2
@MatthewMarlin - Xem câu trả lời của Syakur để biết câu trả lời đúng cho việc chuyển hướng đến một hành động. Bạn đúng rằng bạn không nên gọi bộ điều khiển trực tiếp từ bộ lọc hành động - đó là định nghĩa của khớp nối chặt chẽ.
NightOwl888

1
@Akbari bạn đã thử đặt thuộc tính Thứ tự của các thuộc tính chưa? Ngoài ra FilterScope sẽ tác động đến thứ tự thực hiện.
CRice

79

Ngoài ra, để chuyển hướng, nếu nó đang gọi mã của riêng bạn, bạn có thể sử dụng điều này:

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

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

Nó không phải là một chuyển hướng thuần túy nhưng cho kết quả tương tự mà không cần chi phí không cần thiết.


Bạn DID giúp tôi. Cảm ơn!
Edgar Salazar

25
Lưu ý rằng bạn không nên gọi actionContext.Result.ExecuteResulttừ bên trong bộ lọc hành động của mình - MVC sẽ tự động thực hiện sau khi bộ lọc hành động chạy (với điều kiện actionContext.Resultkhông phải là null).
NightOwl888

12

Tôi đang sử dụng MVC4, tôi đã sử dụng cách tiếp cận sau để chuyển hướng một màn hình html tùy chỉnh khi vi phạm ủy quyền.

Mở rộng AuthorizeAttributenói CutomAuthorizer ghi đè lên OnAuthorizationHandleUnauthorizedRequest

Đăng ký CustomAuthorizertrong RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

khi xác định unAuthorizedcuộc gọi truy cập HandleUnauthorizedRequestvà chuyển hướng đến hành động của bộ điều khiển có liên quan như dưới đây.


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

                                         });

    }
}

9

Có vẻ như bạn muốn thực hiện lại, hoặc có thể mở rộng , AuthorizeAttribute. Nếu vậy, bạn nên chắc chắn rằng bạn thừa hưởng điều đó, và không ActionFilterAttribute, để cho ASP.NET MVC thực hiện nhiều công việc hơn cho bạn.

Ngoài ra, bạn muốn đảm bảo rằng bạn ủy quyền trước khi bạn thực hiện bất kỳ công việc thực tế nào trong phương thức hành động - nếu không, sự khác biệt duy nhất giữa đăng nhập và không phải là trang bạn nhìn thấy khi công việc được hoàn thành.

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

Có một câu hỏi hay với một câu trả lời với nhiều chi tiết hơn ở đây về SO.


5

Hãy thử đoạn mã sau, nó sẽ khá rõ ràng:

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

Điều này hiệu quả với tôi, tôi đã phải kiểm tra các giá trị chuỗi truy vấn nếu bất kỳ người dùng nào cố gắng thay đổi giá trị chuỗi truy vấn và cố gắng truy cập dữ liệu không được ủy quyền cho anh ta hơn là tôi chuyển hướng chúng đến trang tin nhắn trái phép, sử dụng ActionFilterAttribution.
Sameer

3

Đây là một giải pháp cũng tính đến nếu bạn đang sử dụng các yêu cầu 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

Điều này làm việc cho tôi (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

bạn có thể kế thừa bộ điều khiển của mình sau đó sử dụng nó trong bộ lọc hành động của bạn

bên trong lớp ActionFilterAttribution của bạn:

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

bên trong bộ điều khiển cơ sở của bạn:

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

Nhược điểm. điều này là để thay đổi tất cả các bộ điều khiển để kế thừa từ lớp "MyContoder"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.