[C#].Net Core下全局自定義身份過濾器使用AllowAnonymous屬性


假設一種情況:項目中需要做認證和權限控制,而且需要權限才能訪問的控制器要遠多於可以匿名訪問的(類似AO系統那樣,登陸了才能用)。

那在每個控制器上加一個 [Authorize] 是能解決問題,反正正我是覺得麻煩。

而且Core自帶的權限認證機制不滿足於復雜的身份權限認證,打算像在Framework中一樣注冊一個全局過濾器,然后用 [AllowAnonymous] 來放行可以匿名的控制器或者方法。

 

按照官方文檔,自定義身份過濾器推薦實現 IAuthorizationFilter 或者 IAsyncAuthorizationFilter 接口,再順便給他們定義為中間件更好。

例如

 1     public class MyAuthorizeFilter : IAuthorizationFilter
 2     {
 3         public void OnAuthorization(AuthorizationFilterContext context)
 4         {
 5             //do something... 6         }
 7     }
 8 
 9     public class MyAsyncAuthorizeFilter : IAsyncAuthorizationFilter
10     {
11         public Task OnAuthorizationAsync(AuthorizationFilterContext context)
12         {
13             //do someting...14         }
15     }
MyAuthorizeFilter

然后在Startup.cs中注冊全局過濾器

1         public void ConfigureServices(IServiceCollection services)
2         {
3             services.AddMvc(option => { option.Filters.Add(typeof(MyAuthorizeFilter)); });
4         }

 

可是運行時發現,自定義的過濾器無法阻止那些沒有授權的請求!這是為什么?

在控制器上加上  [Authorize] 調試

發現實際上我的過濾器已經被加到了過濾器列隊里,但是本身並沒有執行任何動作。

其實這里也是我自己犯傻了,人家就是一個接口而已,肯定沒有任何操作,單純繼承接口以后指望人家能做什么呢。

 

那我們既要實現原生的權限認證機制(畢竟像未登錄跳轉等功能不用自己實現了),還要增加自定義的認證機制。

后來發現 [Authorize] 屬性會被注冊為AuthorizeFliter過濾器。那就妥了,繼承然后重寫其實現就好。

我的過濾器就變成了這樣。

 1 public class MyAuthorizeFilter : AuthorizeFilter
 2     {
 3 
 4         private static AuthorizationPolicy _policy_ = new AuthorizationPolicy(new[] { new DenyAnonymousAuthorizationRequirement() }, new string[] { });
 5 
 6         public MyAuthorizeFilter() : base(_policy_) { }
 7 
 8         public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
 9         {
10             await base.OnAuthorizationAsync(context);
11             Console.WriteLine("權限檢測");
12         }
13     }

 

說明一下實現AuthorizeFilter基類,必須有一個過濾策略,也就是,這里我采用的是最基礎的DenyAnonymousAuthorizationRequirement(阻止匿名身份的請求)

 

運行,過濾器可以正常過濾沒有授權的請求了,但是無論授權與否,或者是否可匿名訪問,均會執行“權限檢測”那里。

這是為啥?

繼續調試。

發現 [AllowAnonymous] 也被注冊成了過濾器。

 

修改代碼,最終成了這樣

 1     public class MyAuthorizeFilter : AuthorizeFilter
 2     {
 3 
 4         private static AuthorizationPolicy _policy_ = new AuthorizationPolicy(new[] { new DenyAnonymousAuthorizationRequirement() }, new string[] { });
 5 
 6         public MyAuthorizeFilter() : base(_policy_) { }
 7 
 8         public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
 9         {
10             await base.OnAuthorizationAsync(context);
11             if (!context.HttpContext.User.Identity.IsAuthenticated ||
12                 context.Filters.Any(item => item is IAllowAnonymousFilter)) return;
13             //do something
14         }
15     }

 

僅作為一個簡單的學習筆記。如果有更好的方法歡迎指教。

 

又及:

在某篇博客中見過一個問題,大概就是說 context.HttpContext.User.Identity.IsAuthenticate 的值恆定false,后來采用了一大堆不啦不啦的方法自己實現了獲取認證狀態的方法。這篇博客我找不到了。

我也遇到了類似的問題,后來發現是在startup的Configure中沒有啟用身份認證 app.UseAuthentication() ,根據自己的方法自行選擇,例如我后來用IdentityServer4,就變成了 app.UseIdentityServer(); 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM