Alihkan Dari Atribut Filter Tindakan

140

Apa cara terbaik untuk melakukan pengalihan di file ActionFilterAttribute. Saya telah sebuah ActionFilterAttributedisebut IsAuthenticatedAttributeFilterdan yang memeriksa nilai variabel sesi. Jika variabelnya salah, saya ingin aplikasi dialihkan ke halaman login. Saya lebih suka mengalihkan menggunakan nama rute SystemLoginnamun metode pengalihan apa pun pada saat ini akan baik-baik saja.

ryanzec.dll
sumber

Jawaban:

190

Setel filterContext.Result

Dengan nama rute:

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

Anda juga dapat melakukan sesuatu seperti:

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

Jika Anda ingin menggunakan RedirectToAction:

Anda dapat membuat RedirectToActionmetode publik pada pengontrol Anda ( sebaiknya pada pengontrol dasarnya ) yang hanya memanggil dilindungi RedirectToActiondari System.Web.Mvc.Controller. Menambahkan metode ini memungkinkan panggilan publik ke Anda RedirectToAction dari filter.

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

Maka filter Anda akan terlihat seperti ini:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}
CRice
sumber
8
Ini berfungsi, tetapi bukankah seharusnya ada metode RedirectToAction yang tersedia?
Ben Mills
Namun, @BenMills ada, protectedjadi Anda tidak akan memiliki akses ke sana dari filter.
Yakobus
10
Pertanyaan saya sekarang adalah mengapa Microsoft memutuskan untuk membuat filter ini protectedharus ada penjelasan yang masuk akal? Saya merasa sangat kotor mendefinisikan kembali aksesibilitas ini RedirectToActiontanpa memahami mengapa itu dikemas di tempat pertama.
Matthew Marlin
2
@MatthewMarlin - Simak jawaban Syakur untuk jawaban yang tepat untuk mengarahkan ke suatu tindakan. Anda benar bahwa Anda tidak boleh memanggil pengontrol langsung dari filter tindakan - itulah definisi kopling ketat.
NightOwl888
1
@ Akbari sudahkah Anda mencoba menyetel properti Orde atribut? FilterScope juga akan memengaruhi urutan eksekusi.
CRice
79

Alternatifnya untuk pengalihan, jika memanggil kode Anda sendiri, Anda dapat menggunakan ini:

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

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

Ini bukan pengalihan murni tetapi memberikan hasil serupa tanpa biaya tambahan yang tidak perlu.

Syakur Rahman
sumber
Anda DID membantu saya. Terima kasih!
Edgar Salazar
26
Perhatikan bahwa Anda tidak boleh memanggil actionContext.Result.ExecuteResultdari dalam filter tindakan Anda - MVC akan melakukannya secara otomatis setelah filter tindakan berjalan (asalkan actionContext.Resulttidak null).
NightOwl888
12

Saya menggunakan MVC4, saya menggunakan pendekatan berikut untuk mengarahkan ulang layar html kustom setelah pelanggaran otorisasi.

Perpanjang AuthorizeAttributekatakan CutomAuthorizer timpa OnAuthorizationdanHandleUnauthorizedRequest

Daftarkan CustomAuthorizerdi RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

setelah mengidentifikasi unAuthorizedpanggilan akses HandleUnauthorizedRequestdan mengalihkan ke tindakan pengontrol terkait seperti yang ditunjukkan di bawah ini.


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

                                         });

    }
}
pengguna2834076
sumber
9

Sepertinya Anda ingin menerapkan ulang, atau mungkin memperpanjang AuthorizeAttribute,. Jika demikian, Anda harus memastikan bahwa Anda mewarisinya, dan tidak ActionFilterAttribute, agar ASP.NET MVC melakukan lebih banyak pekerjaan untuk Anda.

Selain itu, Anda ingin memastikan bahwa Anda memberi otorisasi sebelum Anda melakukan pekerjaan nyata apa pun dalam metode tindakan - jika tidak, satu-satunya perbedaan antara masuk dan tidak adalah halaman apa yang Anda lihat saat pekerjaan selesai.

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

Ada pertanyaan bagus dengan jawaban dengan detail lebih lanjut di SO.

Tomas Aschan
sumber
5

Coba cuplikan berikut, seharusnya cukup jelas:

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);
  }
}
Muhammad Soliman
sumber
Ini berhasil untuk saya, saya harus memeriksa nilai string kueri jika ada pengguna yang mencoba mengubah nilai string kueri dan mencoba mengakses data yang tidak diizinkan kepadanya daripada saya mengarahkannya ke halaman pesan tidak sah, menggunakan ActionFilterAttribute.
Sameer
3

Berikut adalah solusi yang juga memperhitungkan jika Anda menggunakan permintaan 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);
        }
    }
}
Mike
sumber
2

Ini berfungsi untuk saya (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();
}
mortenma71
sumber
0

Anda dapat mewarisi pengontrol Anda kemudian menggunakannya di dalam filter tindakan Anda

di dalam kelas ActionFilterAttribute Anda:

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

di dalam pengontrol dasar Anda:

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

Kontra. ini untuk mengubah semua pengontrol untuk mewarisi dari kelas "MyController"

Muhammad Soliman
sumber