一、前言
Filter
是延續Asp.Net Mvc
的產物,同樣保留了五種的Filter
,分別是Authorization Filter
、Resource Filter
、Action Filter
、Exception Filter
、Result Filter
。通過不同的Filter
可以有效處理一些共通的動作。
(一)Filter 介紹
- Authorization Filter:優先級1;權限過濾器,通常在
Filter Pipleline
中首先執行,並用於決定當前客戶端Request
請求權限的身份授權驗證 - Resource Filter:優先級2;資源過濾器,通常在
Authorization
後面執行,同時在後面的其它過濾器完成後還會執行;作用於Api
資源授權、緩存處理等一些可以性能原因的攔截,因爲運行在模型綁定前,所以這裏的操作都會影響模型綁定。 - Action Filter:優先級3;方法過濾器,執行於
Action
方法前後,用於Action
審計日誌、傳遞參數和方法返回值的處理。 - Exception Filter:優先級4;異常過濾器,被應用全局策略處理未處理的異常被寫入響應體。
- Result Filter:優先級5;返回值過濾器,可以執行於
Action
結果之前執行,且執行Action
成功後執行,使用邏輯一般圍繞Action
入參的驗證和格式化返回值。
(二)Filter 流程圖
二、Filter 實現&場景應用
在開始寫代碼前需引用nuget包或包含的集成包
Microsoft.AspNetCore.Mvc.Abstractions
均可;下面我用異步的方式,繼承相應過濾器實現對應功能,說這麼多,還是看代碼吧!
(一)Authorization Filter
權限過濾器,通過 Authorization Filter
可以實現複雜的 防篡改
、驗證XsrfToken防僞令牌
等操作。具體代碼如下:
/// <summary>
/// SB過濾器 - 權限
/// </summary>
public class SBAuthorizationFilterAttribute : Attribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
// 參數防篡改
// 驗證XsrfToken防僞令牌
// ..
}
}
(二)Resource Filter
資源過濾器,通過 Resource Filter
可以進行 Api資源授權
、 緩存處理
等複雜操作。具體代碼如下:
/// <summary>
/// SB過濾器 - 資源
/// </summary>
public class SBResourceFilterAttribute : Attribute, IAsyncResourceFilter
{
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
// 控制器實例化之前,執行的動作
// 驗證是否跳過Api資源授權
// 緩存處理
await next();
// Action的Result Filter(befor)執行後再執行
}
}
(三)Action Filter
方法過濾器,執行於控制器方法的前後置動作,前置動作可以應用於 參數傳遞
,後置動作可以應用於 Action審計日誌
。具體代碼如下:
/// <summary>
/// SB過濾器 - 方法
/// </summary>
public class SBActionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// Action執行前,執行的動作
// 參數傳遞
var result = await next();
// Action的執行後,執行的動作
// Action審計日誌
}
}
(四)Exception Filter
異常過濾器,作用於全局的異常處理,當系統發生未捕獲異常時會觸發此過濾器進行處理,應用於 全局異常捕獲
、異常日誌處理
。具體代碼如下:
/// <summary>
/// SB過濾器 - 全局異常
/// </summary>
public class SBExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
if (context.ExceptionHandled)//異常是否已處理
return;
// 異常處理
context.Result = new ObjectResult(
new { code = "412", msg = "異常信息" });
// 處理完告訴系統此異常已處理
context.ExceptionHandled = true;
}
}
(五)Result Filter
返回值過濾器,執行於結果執行之前/之後,前置動作可以應用於 Dto模型驗證
,後置動作可以應用於 格式化返回值
。具體代碼如下:
/// <summary>
/// SB過濾器 - 返回值
/// </summary>
public class SBResultFilter : IAsyncResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
// 結果執行前,執行的動作
// Dto模型驗證
var result = await next();
// 結果執行後,執行的動作
// 格式化返回值
}
}
三、Asp.Net Core 過濾器的註冊方式
Asp.Net Core
中 過濾器 分爲兩種註冊方式 全局
和 局部
,根據過濾器的使用場景及需要我們可以選擇不同的註冊方式。
(一)全局註冊
過濾器也區分作用於全局和局部之分,作用於全局就不需要局部(類、控制器等)每一個進行代碼註冊,相對方便非常多。具體代碼如下:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddMvc(options => {
options.Filters.Add<SBAuthorizationFilterAttribute>();
options.Filters.Add<SBResourceFilterAttribute>();
options.Filters.Add<SBActionFilter>();
options.Filters.Add<SBExceptionFilter>();
options.Filters.Add<SBResultFilter>();
});
//...
}
(二)局部註冊
場景假設幾大過濾器中有個過濾器只想作用於局部作用,過濾器可能就需要局部註冊 ServiceFilter
和 TypeFilter
。
ps:幾大過濾器沒有繼承 Attribute
不能使用特性的註冊方式,想了解特性註冊方式可以百度,暫時還沒寫。
ServiceFilter
和 TypeFilter
的區別:
ServiceFilter
和TypeFilter
都實現了IFilterFactory
。ServiceFilter
需要對自定義的Filter
進行註冊,TypeFilter
不需要。ServiceFilter
的Filter
生命週期源自於註冊方式,而TypeFilter
每次都會創建一個新的實例。
1. ServiceFilter 使用方式
控制器中具體代碼如下:
[ServiceFilter(typeof(SBAuthorizationFilterAttribute))]//過濾器註冊到控制器中
[Route("api/[controller]")]
[ApiController]
public class DefaultController : ControllerBase
{
// GET: api/Default
[HttpGet]
[ServiceFilter(typeof(SBAuthorizationFilterAttribute))]//過濾器註冊到方法中
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
註冊服務中具體代碼如下:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddMvc();
// 註冊過濾器服務,使用ServiceFilter 方式必須要註冊 否則會報沒有註冊該服務的相關異常
services.AddSingleton<SBAuthorizationFilterAttribute>();
//...
}
2. TypeFilter 使用方式
TypeFilter
的用法就比較方便,只要控制器或者方法註冊即可。
[TypeFilter(typeof(SBAuthorizationFilterAttribute))]//過濾器註冊到控制器中
[Route("api/[controller]")]
[ApiController]
public class DefaultController : ControllerBase
{
// GET: api/Default
[HttpGet]
[TypeFilter(typeof(SBAuthorizationFilterAttribute))]//過濾器註冊到方法中
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
四、Asp.Net Core 過濾器調用順序
- 全局->局部
- Controller->Action
- 先註冊先調用