日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【复杂系统迁移 .NET Core平台系列】之认证和授权

發布時間:2023/12/4 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【复杂系统迁移 .NET Core平台系列】之认证和授权 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

源寶導讀:微軟跨平臺技術框架—.NET Core已經日趨成熟,已經具備了支撐大型系統穩定運行的條件。本文將介紹明源云ERP平臺從.NET Framework向.NET Core遷移過程中的實踐經驗。

一、背景

? ?隨著ERP的產品線越來越多,業務關聯也日益復雜,應用間依賴關系也變得錯綜復雜,單體架構的弱點日趨明顯。19年初,由于平臺底層支持了分應用部署模式,將ERP從應用子系統層面進行了切割分離,邁出了從單體架構向微服務架構轉型的堅實一步。不久的將來,ERP會進一步將各業務拆分成眾多的微服務,而微服務勢必需要進行容器化部署和運行管理,這就要求ERP技術底層必須支持跨平臺,所以將現有ERP系統從.NET Framework遷移到 .NET Core平臺勢在必行。

? ? 上一篇我們講述了Erp改造.Net Core之靜態文件,這一篇我們將講述在認證和授權改造過程中遇到的問題和解決思路。

二、關于認證和授權

? ? 權限控制是應用程序中最常見的需求,無論是在Asp.Net還是Asp.Net Core中都有相應的支持,而權限控制在框架層面支持主要是兩部分,身份認證和身份授權:

  • 身份認證:識別當前請求的用戶信息,一般是通過加密的Cookies實現。

  • 身份授權:識別當前請求是否有訪問指定資源的權限,一般是根據當前請求識別的用戶信息,結合角色權限相關配置來判斷。

三、Asp.Net認證和授權的實現

? ? 這里不區分Asp.Net WebForm和Asp.Net MVC,因為兩者都是基于HttpModule來進行身份認證和授權。

? ?在Asp.Net中認證是通過FormsAuthenticationModule實現,授權是通過UrlAuthorizationModule實現,需要在web.config中做如下配置:

<system.web><authentication mode="Forms"><forms loginUrl="/PubPlatform/Login/index.aspx" name="userToken" defaultUrl="/PubPlatform/Nav/Home/Default.aspx" timeout="300" /></authentication><authorization><deny users="?" /><!--禁止匿名用戶的訪問--></authorization> </system.web><!--管理員有modeling目錄的訪問權限--> <location path="modeling"><system.web><authorization><allow roles="Admin"/><deny users="*"/></authorization></system.web> </location>

? ? 簡述一下用戶訪問網站授權一個流程:

  • 假設用戶訪問首頁/PubPlatform/Nav/Home/Default.aspx。

  • UrlAuthorizationModule 根據禁止匿名用戶訪問的配置,要求用戶進行身份認證。

  • 跳轉到登陸頁面/ PubPlatform/ Login/index.aspx進行身份認證。

  • 服務端判斷用戶輸入用戶密碼信息。

  • 如果驗證通過將認證信息寫入Repsonse的Cookies中并跳轉到/PubPlatform/Nav/Home/Default.aspx。

  • UrlAuthorizationModule 根據配置發現已經有用戶信息直接,開始進入到HttpHandler處理程序。

  • PS:整個認證過程遠比這個復雜,因為本文重點不在這里,只做簡單的描述,了解基本流程即可,有興趣可以參考https://www.cnblogs.com /fish-li/archive/2012/04/15/2450571.html。

    ? ? 第二段配置中,通過用戶所在的組來控制是否有modeling目錄的訪問權限,如果需要更多的權限配置可以添加更多類似的配置,實際在使用過程中很少使用這種方式,因為用戶角色和頁面會有很多,配置會很多而且不能實現動態配置,所以一般是在應用程序中處理,在Webform中一般采用類似如下方式:

    public class BacePage:Page {protected override void OnLoad(EventArgs e){//在這里根據HttpContext.User來獲取用戶信息然后獲取角色權限來判斷當前資源可否訪問base.OnLoad(e);} }

    ? ? 在Mvc中一般采用繼承自AuthorizationFilterAttribute來處理,邏輯跟上述代碼中演示的類似。

    四、Asp.Net Core

    ? ? 在Core中引入Authentication需要在Startup.cs進行引入,一般和老版本一樣使用Cookies做認證信息的承載,承載的代碼如下:

    public void ConfigureServices(IServiceCollection services) {...services.AddAuthentication("Cookies").AddCookie("Cookies");... } public void Configure(IApplicationBuilder app, IHostingEnvironment env) {...app.UseAuthentication();... }

    ? ? 在ConfigureServices(應用初始化過程),引入了Cookies作為默認的認證方式,在Configure(管道初始化)過程中引入認證的中間件。下面會簡要分析下認證和授權的過程:

  • 請求進入Authentication Middleware中間件之后首先會IAuthentication RequestHandler 接口做權限判斷,這個組件主要使用來做遠程認證的,例如SSO登錄的場景。然后再做默認的認證:以Cookies認證為例,主要是讀取Cookies的信息到HttpContext.User中。

  • 經過中間件之后會進入AuthorizeFilter中(這里和認證和授權的核心地方)。

  • 獲取全局,Controller,Action之上的元數據計算之后得出AuthorizationPolicy。

  • 通過IPolicyEvaluator調用Authentication模塊進行認證信息解析。

  • 通過IPolicyEvaluator攜帶Authentication結果調用Authentization模塊進行授權信息解析。

  • ? ? 核心代碼如下:

    //AuthenticationMiddleware 部分代碼 public async Task Invoke(HttpContext context) {context.Features.Set(new AuthenticationFeature{OriginalPath = context.Request.Path,OriginalPathBase = context.Request.PathBase});// Give any IAuthenticationRequestHandler schemes a chance to handle the requestvar handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()){var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;if (handler != null && await handler.HandleRequestAsync()){return;}}var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();if (defaultAuthenticate != null){var result = await context.AuthenticateAsync(defaultAuthenticate.Name);if (result?.Principal != null){context.User = result.Principal;}}await _next(context); } // AuthorizeFilte部分代碼 public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context) {if(context == null){throw new ArgumentNullException(nameof(context));}if (!context.IsEffectivePolicy(this)){return;}// IMPORTANT: Changes to authorization logic should be mirrored in security's AuthorizationMiddlewarevar effectivePolicy = await GetEffectivePolicyAsync(context);if (effectivePolicy == null){return;}var policyEvaluator = context.HttpContext.RequestServices.GetRequiredService<IPolicyEvaluator>();var authenticateResult = await policyEvaluator.AuthenticateAsync(effectivePolicy, context.HttpContext);// Allow Anonymous skips all authorizationif (HasAllowAnonymous(context)){return;}var authorizeResult = await policyEvaluator.AuthorizeAsync(effectivePolicy, authenticateResult, context.HttpContext, context);if (authorizeResult.Challenged){context.Result = new ChallengeResult(effectivePolicy.AuthenticationSchemes.ToArray());}else if (authorizeResult.Forbidden){context.Result = new ForbidResult(effectivePolicy.AuthenticationSchemes.ToArray());} }

    ? ? 如果有興趣的話可以繼續往里面跟蹤一下代碼發現最終起作用的是IAuthentication Handler和IAuthorizationHandler,而最終這兩個Handler的引入在Core中對應兩個概念:

    • AuthenticationScheme 認證計劃。

    • AuthorizationRequirement 授權條件。

    ? ? 最終Core的認證和授權一般都是通過這兩個來進行擴展,這里特別說明一點,在Mvc Core中將身份認證和授權進行了統一的規劃。因為在認證過程中,MVC Core只是只是解析,但并不實際將Http請求進行返回處理。實際過程是在AuthorizationRequirement進行處理的,這里特別提到Mvc Core中的默認授權DenyAnonymousAuthorizationRequirement,通過這個授權條件判斷是否有認證的用戶信息來進行權限的判斷。

    資源能否訪問這個理解為授權,那么身份認證只是授權的一種方式。

    ? ? 在Asp.Net WebFrom中使用基于HttpModule進行身份認證會丟失掉很多元數據的信息,因為最終方法的執行是在HttpHandler上,而HttpModule并不知道那個Handler也不知道是那個方法,就會大量使用HttpContext的解析,提高了復雜度。

    ? ? 如果在HttpModule中進行,如果有多種身份認證方式,那么無論最終資源需要何種方式都會經過很多HttpModule,走了無謂的分支。

    ? ? 另外Webfrom中授權一般寫在基類中,基類必定會引入不同的繼承分支,這樣也不便于維護.對比Mvc Core中使用的特性標記+策略者的使用方式,更加利于維護和擴展,而不用對原有邏輯進行變動。

    ? ? 對比Asp.Net MVC中其中有IAuthenticationFilter和IAuthorizationFilter來處理授權和認證,然而在Asp.Net MVC Core中 只有IAuthorizationFilter。

    ? ? 對于資源的訪問應該只有可否訪問的判斷即授權,而是否身份認證只能說是判斷授權一種常用方式,在MVC Core中將認證通過DenyAnonymousAuthorizationRequirement融入授權以后,真正的將授權和認證融為一體,而非之前看似兩個并行的概念,相互不同的處理邏輯。

    ? ? 在Mvc Core通過AOP進行接入,然后一系列的封裝,最終將身份和授權通過Scheme + IAuthrenticationHandler和Requirement + AuthorizationHandler,這種類似于策略者模式的方式,對外提供擴展。更加易于擴展,而實際并不用太多考慮AOP部分的邏輯。最終授權和認證之需要我們進行Attribute標記然后MVC Core會自動加載到自己的元數據中,另外在RazorPage還可以主動調用如下方法進行授權的添加:

    //對目錄進行授權 RazorPageOptions.Conventions.AuthorizeFolder(); //對頁面進行授權 RazorPageOptions.Convertions.AuthorizePage();

    五、ERP認證和授權

    ? ? ERP頁面的部分使用傳統webform的認證體系,而提供的接口部分使用了自定義HttpModule的方式,由于很多ERP演化升級過程中被動接受了很多身份認證方式的接入,所以原本實現授權的HttoModule的邏輯變得異常復雜,而這一次在改造Core的過程中進行了全面的改造后面會進行講述。同樣授權也是一樣,將原本實現在Page基類中的復雜的判斷邏輯進行了改造。

    ? ? ERP在pub接口的身份認證方面需要實現對如下不同的方式:

    • Pub接口

    • 內部集成

    • 接口管家

    • Mip集成

    • OA集成

    ? ? 之前講過ERP是通過元數據來驅動的頁面邏輯,權限實際是通過通過元數據配置到界面元素上的權限點來進行標識。通過常用的用戶-角色-權限的模型模型來關聯用戶和權限點,然后通過在Page的基類中通過拿到用戶的權限來判斷是否有當前URL的訪問權限,在按鈕渲染的時候來獲取是否有該按鈕的權限點來控制是否顯示。

    ? ? 在這次的改造過程中我們進行了如下改造:

  • Mvc Core CookiesAuthentication中間件來實現頁面的身份認證。

  • 擴展MVC Core 的 AuthenticationScheme來實現接口的身份認證。

  • 擴展MVC Core 的 Authentization Policy +Requirement來實現頁面的身份授權。

  • 下面通過這三部分進行講述。

    5.1、CookiesAuthentication身份認證

    ? ? MVC Core 自帶的基于Cookies的身份認證已經能滿足我們的需求,只需要稍微進行一下配置即可。通過一張圖我們了解下整個的身份認證流程,使用代碼參考本章開頭Asp.Net Core對認證和授權進行分析的部分。

    ? ? 因為只是使用來說已經比較簡單這里不做過多的描述。這里有一個點需要注意,在Cookie的認證中如果是負載均衡的場景,兩個不同進程的引用需要都可以進行客戶端Cookies的解密。那么就需要共享加解密的key,這里我們使用MVC Core自帶的基于Entity Framework Core 的密鑰持久化方式,通過存放到數據庫來實現密鑰的共享。這部分內容可以參考:https://docs.microsoft.com/zh-cn/aspnet/core/security/data-protection/implementation/key-storage-providers?view=aspnetcore-3.1&tabs=visual-studio。

    5.2、Pub接口的身份認證

    ? ? 除了頁面訪問以及頁面ajax請求這些事基于Cookies的身份認證之外,在提供的接口用了其他的認證方式,這次將所有接口的認證方式進行了抽象,統一使用OpenApi的Scheme進行認證,而實際各種不同的認證方式我們是通過實入AuthenticationMiddleware中調用的IAuthenticationRequestHandler來實現的。首先我們看一下執行的流程:

    ? ? 之前有一篇關于Mvc Core的Controller改造的文章,其中將pub接口的發現和特性路由擴展進行了擴展,這里我們在擴展的地方添加OpenApi類型Scheme的元數據。

    ? ? 因為我們的接口統一是使用/pub/開頭的所以我們選擇使用擴展IAuthentication RequestHandler來實現,這樣在判斷是否要進行認證的時候需要判斷url是否以pub開頭即可,下面是類圖:

    ? ? 其中核心就是MockUserAuthHandler,因為在Erp的接口中都會用到用戶相關的信息,所以我們所有的pub接口操作實際的身份認證都是模擬了用戶的認證,這里將這個概念顯式的移動到基類之中,我們通過如下代碼進行接入:

    public static AuthenticationBuilder AddOpenApiAuth(this AuthenticationBuilder builder) {builder.AddScheme(AppConst.ApiSchemeName, AppConst.ApiSchemeName,null);return builder.AddScheme<ApiAuthOptions, OpenApiAuthHandler>(AppConst.OpenApi, AppConst.OpenApi, null).AddScheme<ApiAuthOptions, AccessTokenAuthHandler>(AppConst.AccessToken, AppConst.AccessToken, null).AddScheme<ApiAuthOptions, OAuthV1AuthHandler>(AppConst.OAuthV1, AppConst.OAuthV1, null).AddScheme<ApiAuthOptions, OAuthV2AuthHandler>(AppConst.OAuthV2, AppConst.OAuthV2, null).AddScheme<ApiAuthOptions, InternalIntegrationAuthHandler>(AppConst.InternalIntegration, AppConst.InternalIntegration, null); }

    ? ? 這里我們添加了眾多的Scheme只是為了在AuthenticationMiddleware中處理請求并進行模擬用戶登錄,并未有實際的Action上有此Sheme,在Action上使用的只有AppConst.ApiSchemeName(“OpenApiScheme”)。

    ? ? 在Cookies的認證的流程中因為是在登錄過程中將認證信息寫到Cookies中,而其他請求只需要進行Cookies解析即可獲得用戶信息。而pub接口請求是在一個用戶請求過程中完成整個過程,實際是通過解析Header的特定內容,然后跟保存在Erp中的認證信息進行對比來確定身份,最后在模擬用戶之后,進行登錄操作來完成整個身份認證的流程。

    ? ? 這里我們采用擴展IAuthentication RequestHandler的方式有如下考慮:

  • 如果采用IAuthenticationHandler + Sheme,Core的標準是按照不同的請求使用不同Scheme無法支持,而實際來說都是通過pub接口進行區分,并沒有區分到具體的請求。

  • 目前ERP的認證方式跟行業標準方案不同,以后如果接入標準方案,增加Scheme更加容易擴展并兼容現有方案。

  • IAuthenticationRequestHandler官方給出是遠程認證時候使用,在以后前后端分離加上微服務的升級過程中,只需要修改這部分請求中認證信息發送給遠程服務器認證即可,更加符合官方推薦使用的風格。

  • ? 綜合來說采取IAuthentication RequestHandler而不采用IAuthenticationHandler + Sheme 方式,還是基于官方給出的推薦使用風格和Erp擴展需求綜合考慮而來。

    5.3、Razor頁面授權

    ? ? 在頁面改造篇我們講述了頁面改造的過程,我們知道RazorPage實際是類似CodeBehind的模式,通過PageModel的OnGet方法,每個頁面都有對應的PageModel,所以我們這里定義的BasePageModel基類如下:

    //其他Attribute [Authorize(Policy = AppConst.UserAuth,AuthenticationSchemes = “Cookies”)] public abstract class BasePageModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel {protected readonly MapPageContext _mapPageContext;protected BasePageModel(MapPageContext mapPageContext){_mapPageContext = mapPageContext;VerifyApplication.CheckStatus();} }

    ? ? 這里我們使用Cookies的Scheme進行授權,特別的是我們還增加了AuthentizationPolicy的定義,通過定義的Policy加上PolicyProvider來實現不同的Policy的切換,Policy的使用代碼如下:

    public static IMvcBuilder AddFrontend(this IMvcBuilder builder) {builder.AddRazorPagesOptions(options =>{//…//建模的權限options.Conventions.AuthorizeFolder(“/modeling”, AppConst.ModelingAuth);});//頁面權限builder.Services.AddMapAuth();//... } //注冊 private static void AddMapAuth(this IServiceCollection services) {services.AddSingleton();services.TryAddEnumerable(ServiceDescriptor.Transient());services.TryAddEnumerable(ServiceDescriptor.Transient());services.TryAddEnumerable(ServiceDescriptor.Transient()); }//Policy實現 internal class MapAuthPolicyProvider : IAuthorizationPolicyProvider{private DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }public MapAuthPolicyProvider(IOptions<AuthorizationOptions> options){FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);}public Task<AuthorizationPolicy> GetPolicyAsync(string policyName){if (policyName.StartsWith(AppConst.ModelingAuth, StringComparison.OrdinalIgnoreCase)){var policy = new AuthorizationPolicyBuilder();policy.AddRequirements(new ModelingRequirement());return Task.FromResult(policy.Build());}if (policyName.StartsWith(AppConst.AppAuth, StringComparison.OrdinalIgnoreCase)){var policy = new AuthorizationPolicyBuilder();policy.AddRequirements(new AppAuthRequirement());return Task.FromResult(policy.Build());}if (policyName.StartsWith(AppConst.UserAuth, StringComparison.OrdinalIgnoreCase)){var policy = new AuthorizationPolicyBuilder();policy.AddRequirements(new UserAuthRequirement());return Task.FromResult(policy.Build());}//返回默認的認證return FallbackPolicyProvider.GetPolicyAsync(policyName);}public Task<AuthorizationPolicy> GetDefaultPolicyAsync(){return FallbackPolicyProvider.GetDefaultPolicyAsync();} }

    ? ? 通過上述代碼實現了不同策略使用不同的Requirement進行授權的校驗,至于授權校驗邏輯就是常見的用戶權限判斷。下面是整體的執行流程:

    六、總結

    ? ? Core認證和授權改造主要是要對Core的認證和授權的邏輯要清晰,這里核心就是去扒源碼,由于之前對Asp.Net MVC的了解,直接就從AuthorizeFilter入手很快就可以找到切入點,然后了解到整個Core認證和授權的核心。

    ? ? 權限這部分的改造不僅僅只是代碼的遷移,也是風格的一個改造,將原來認證和授權的大泥球的設計,通過Core提供的Scheme+Requirement的擴展進行結合的重新設計。

    ------ END ------

    作者簡介

    熊同學:?研發工程師,目前負責ERP運行平臺的設計與開發工作。

    也許您還想看

    【復雜系統遷移 .NET Core平臺系列】之遷移項目工程

    【復雜系統遷移 .NET Core平臺系列】之界面層

    【復雜系統遷移 .NET Core平臺系列】之靜態文件

    招商城科走進武漢研發中心,現場編碼解鎖平臺內核技術

    如何解決大批量數據保存的性能問題

    總結

    以上是生活随笔為你收集整理的【复杂系统迁移 .NET Core平台系列】之认证和授权的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。