ASP.NET Core的全域性攔截器(在頁面回發時,如果判斷當前請求不合法,不執行OnPost處理器)

三生石上(FineUI控件)發表於2024-05-15

ASP.NET Core RazorPages中,我們可以在頁面模型基類中過載OnPageHandlerExecuting方法。

下面的例子中,BaseModel繼承自 PageModel,是所有頁面模型的基類。

推薦方案:
在BaseModel.cs中,過載OnPageHandlerExecuting方法(看下面程式碼中的註釋):

public override void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
    base.OnPageHandlerExecuting(context);

    if (IsPostBack)
    {
        // 回發請求時,檢索請求資料或者Cookie,來驗證當前訪問是否有效。請求無效時,彈出錯誤提示,不再執行Page_Load和回發事件。
        if (!String.IsNullOrEmpty(Request.Query["error"]))
        {
            ShowNotify("身份驗證失敗!");

            // Setting Result to a non-null value inside a page filter will short-circuit the page and any remaining page filters.
            // 設定context.Result=UIHelper.Result(),可以中斷頁面繼續執行(跳過接下來的 Page_Load 和回發事件)。
            context.Result = UIHelper.Result();
        }
    }
}

微軟官方文件:https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.filters.pagehandlerexecutingcontext?view=aspnetcore-8.0

上述文件中,在解釋 Result 屬性時,專門提到了這個事情:

在頁面過濾器內將 Result 設定為非空值將使該頁面和任何剩餘的頁面過濾器短路。

延伸閱讀
===================
其實上述方案在6年前釋出 AppBoxCore 時已經存在了,只不過在 AppBoxCore 中做的更加工程化,也更加清晰。

當前的需求是要求有些頁面需要進行身份驗證,而一些公開的頁面不需要身份驗證。

1. 我們首先定義 CheckPowerAttribute 過濾器。

namespace AppBoxCore.Dapper
{
    /// <summary>
    /// AppBoxCore自定義許可權驗證過濾器
    /// </summary>
    public class CheckPowerAttribute : ResultFilterAttribute
    {
        /// <summary>
        /// 許可權名稱
        /// </summary>
        public string Name { get; set; }
        
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            HttpContext context = filterContext.HttpContext;
            // 許可權驗證不透過
            if (!String.IsNullOrEmpty(Name) && !BaseModel.CheckPower(context, Name))
            {
                if (context.Request.Method == "GET")
                {
                    BaseModel.CheckPowerFailWithPage(context);

                    // -修正越權訪問頁面時會報錯[伺服器無法在傳送 HTTP 標頭之後追加標頭](龍濤軟體-9374)。
                    filterContext.Result = new EmptyResult();
                }
                else if (context.Request.Method == "POST")
                {
                    BaseModel.CheckPowerFailWithAlert();
                    filterContext.Result = UIHelper.Result();
                }
            }
        }

    }
}

參考文件:http://stackoverflow.com/questions/9837180/how-to-skip-action-execution-from-an-actionfilter  

這個文件也相關有參考價值,當時遇到一個報錯:

伺服器無法在傳送 HTTP 標頭之後追加標頭

如果需要在 GET 請求中結束當前請求,也需要設定 new EmptyResult()。

2. 然後需要進行身份驗證的頁面,在頁面模型上定義此屬性即可。
比如 Admin 目錄下的 Config 頁面:

[CheckPower(Name = "CoreConfigView")]
public class ConfigModel : BaseAdminModel
{
...
}

  

相關文章