2021-10-15 11:27

讓 Net core 3.1 的 PageModel handler 可以用 AuthorizeAttribute

Razor Page 的 AuthorizeAttribute 只能用在 class 上,這樣就做不到細部的權限管控,為了讓 handler 也能用 AuthorizeAttribute 可以從 IPageFilter 進行處裡:

  1. using System.Linq; 
  2. using System.Reflection; 
  3. using System.Security.Claims; 
  4. using Microsoft.AspNetCore.Authorization; 
  5. using Microsoft.AspNetCore.Mvc; 
  6. using Microsoft.AspNetCore.Mvc.Filters; 
  7.  
  8. namespace XXXXX.Api.Filters 
  9. { 
  10.    public class HandlerAuthorizeFilter : IPageFilter 
  11.    { 
  12.        /// <summary>在完成模型系結之後,于處理常式方法執行之前呼叫。</summary> 
  13.        public void OnPageHandlerExecuting(PageHandlerExecutingContext context) 
  14.        { 
  15.            if(context.HandlerMethod == null) { return; } 
  16.  
  17.            /* 取得 handler 上的 AuthorizeAttribute */ 
  18.            var attr = context.HandlerMethod.MethodInfo 
  19.               .GetCustomAttribute<AuthorizeAttribute>(); 
  20.            if (attr == null) { return; } 
  21.  
  22.            /* 當前登入的使用者 */ 
  23.            ClaimsPrincipal user = context.HttpContext.User; 
  24.  
  25.            /* 檢查是否符合腳色權限 */ 
  26.            bool isAuth = attr.Roles.Split(',').Any(user.IsInRole); 
  27.  
  28.            /* 沒權限就給予 ForbidResult */ 
  29.            if (!isAuth) { context.Result = new ForbidResult(); } 
  30.        } 
  31.  
  32.  
  33.        /// <summary>在選取處理常式方法之後,但在進行模型系結之前呼叫。</summary> 
  34.        public void OnPageHandlerSelected(PageHandlerSelectedContext context) { } 
  35.  
  36.  
  37.        /// <summary>在處理常式方法執行之後,在動作結果執行之前呼叫。</summary> 
  38.        public void OnPageHandlerExecuted(PageHandlerExecutedContext context) { } 
  39.    } 
  40. } 

接著在 Startup.cs 進行過濾器配置:

  1. public void ConfigureServices(IServiceCollection services) 
  2. { 
  3.    //... 
  4.  
  5.    IMvcBuilder mvcBuilder = services 
  6.        .AddRazorPages(options => 
  7.        { 
  8.            //... 
  9.        }) 
  10.        .AddMvcOptions(options => 
  11.        { 
  12.            //... 
  13.            options.Filters.Add(new HandlerAuthorizeFilter()); 
  14.        }) 
  15.        ; 
  16.  
  17.    //... 
  18. } 

然後在 PageModel 就可以用下面的方式撰寫:

  1. public class IndexModel : PageModel 
  2. { 
  3.    [Authorize(Roles = "Admin")] 
  4.    public IActionResult OnGet() 
  5.    { 
  6.        return Page(); 
  7.    } 
  8. } 

0 回應: