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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ocelot 中间件的变化

發(fā)布時(shí)間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ocelot 中间件的变化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

ocelot 中間件的變化

Intro

之前我們使用 ocelot 的時(shí)候自定義了一些中間件來實(shí)現(xiàn)我們定制化的一些需求,最近博客園上有小伙伴問我怎么使用,他用的版本是 16.0 版本,16.0 和 17.0 版本的差異不是特別大,就以 17.0 版本為例看一下 ocelot 中間件的變化

Sample

還是拿之前的一個(gè)自定義認(rèn)證授權(quán)的一個(gè)中間件為例,中間件做的事情主要是

  • 基于 Resource(API Path) 以及 請(qǐng)求 Method 查詢需要的權(quán)限

  • 如果不需要用戶登錄就可以訪問,就直接往下游服務(wù)轉(zhuǎn)發(fā)

  • 如果需要權(quán)限,判斷當(dāng)前登錄用戶的角色是否有對(duì)應(yīng)的角色可以訪問

  • 如果可以訪問就轉(zhuǎn)發(fā)到下游服務(wù),如果沒有權(quán)限訪問根據(jù)用戶是否登錄,已登錄返回 403 Forbidden,未登錄返回 401 Unauthorized

  • Before

    之前的實(shí)現(xiàn)(基于 13.x 版本)詳細(xì)可以參考:https://www.cnblogs.com/weihanli/p/custom-authentication-authorization-in-ocelot.html

    大致代碼如下:

    public?class?UrlBasedAuthenticationMiddleware?:?Ocelot.Middleware.OcelotMiddleware {private?readonly?IConfiguration?_configuration;private?readonly?IMemoryCache?_memoryCache;private?readonly?OcelotRequestDelegate?_next;public?UrlBasedAuthenticationMiddleware(OcelotRequestDelegate?next,?IConfiguration?configuration,?IMemoryCache?memoryCache,?IOcelotLoggerFactory?loggerFactory)?:?base(loggerFactory.CreateLogger<UrlBasedAuthenticationMiddleware>()){_next?=?next;_configuration?=?configuration;_memoryCache?=?memoryCache;}public?async?Task?Invoke(DownstreamContext?context){var?permissions?=?await?_memoryCache.GetOrCreateAsync("ApiPermissions",?async?entry?=>{using?(var?conn?=?new?SqlConnection(_configuration.GetConnectionString("ApiPermissions"))){entry.AbsoluteExpirationRelativeToNow?=?TimeSpan.FromHours(1);return?(await?conn.QueryAsync<ApiPermission>("SELECT?*?FROM?dbo.ApiPermissions")).ToArray();}});var?result?=?await?context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);context.HttpContext.User?=?result.Principal;var?user?=?context.HttpContext.User;var?request?=?context.HttpContext.Request;var?permission?=?permissions.FirstOrDefault(p?=>request.Path.Value.Equals(p.PathPattern,?StringComparison.OrdinalIgnoreCase)?&&?p.Method.ToUpper()?==?request.Method.ToUpper());if?(permission?==?null)//?完全匹配不到,再根據(jù)正則匹配{permission?=permissions.FirstOrDefault(p?=>Regex.IsMatch(request.Path.Value,?p.PathPattern,?RegexOptions.IgnoreCase)?&&?p.Method.ToUpper()?==?request.Method.ToUpper());}if?(!user.Identity.IsAuthenticated){if?(permission?!=?null?&&?string.IsNullOrWhiteSpace(permission.AllowedRoles))?//默認(rèn)需要登錄才能訪問{//context.HttpContext.User?=?new?ClaimsPrincipal(new?ClaimsIdentity(new[]?{?new?Claim(ClaimTypes.Name,?"Anonymous")?},?context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey));}else{SetPipelineError(context,?new?UnauthenticatedError("unauthorized,?need?login"));return;}}else{if?(!string.IsNullOrWhiteSpace(permission?.AllowedRoles)?&&!permission.AllowedRoles.Split(new[]?{?','?},?StringSplitOptions.RemoveEmptyEntries).Any(r?=>?user.IsInRole(r))){SetPipelineError(context,?new?UnauthorisedError("forbidden,?have?no?permission"));return;}}await?_next.Invoke(context);} }

    New

    來看一下在新版本(16.x/17.x)的 ocelot 中實(shí)現(xiàn)代碼是怎樣的

    public?class?ApiPermission {public?string?AllowedRoles?{?get;?set;?}public?string?PathPattern?{?get;?set;?}public?string?Method?{?get;?set;?} }public?class?UrlBasedAuthenticationMiddleware?:?Ocelot.Middleware.OcelotMiddleware {private?readonly?IConfiguration?_configuration;private?readonly?IMemoryCache?_memoryCache;private?readonly?RequestDelegate?_next;public?UrlBasedAuthenticationMiddleware(RequestDelegate?next,?IConfiguration?configuration,?IMemoryCache?memoryCache,?IOcelotLoggerFactory?loggerFactory)?:?base(loggerFactory.CreateLogger<UrlBasedAuthenticationMiddleware>()){_next?=?next;_configuration?=?configuration;_memoryCache?=?memoryCache;}public?async?Task?Invoke(HttpContext?httpContext){//?var?permissions?=?await?_memoryCache.GetOrCreateAsync("ApiPermissions",?async?entry?=>//{//????using?(var?conn?=?new?SqlConnection(_configuration.GetConnectionString("ApiPermissions")))//????{//????????entry.AbsoluteExpirationRelativeToNow?=?TimeSpan.FromHours(1);//????????return?(await?conn.QueryAsync<ApiPermission>("SELECT?*?FROM?dbo.ApiPermissions")).ToArray();//????}//});var?permissions?=?new[]{new?ApiPermission(){PathPattern?=?"/api/test/values",Method?=?"GET",AllowedRoles?=?""},new?ApiPermission(){PathPattern?=?"/api/test/user",Method?=?"GET",AllowedRoles?=?"User"},new?ApiPermission(){PathPattern?=?"/api/test/admin",Method?=?"GET",AllowedRoles?=?"Admin"},};var?downstreamRoute?=?httpContext.Items.DownstreamRoute();var?result?=?await?httpContext.AuthenticateAsync(downstreamRoute.AuthenticationOptions.AuthenticationProviderKey);if?(result.Principal?!=?null){httpContext.User?=?result.Principal;}var?user?=?httpContext.User;var?request?=?httpContext.Request;var?permission?=?permissions.FirstOrDefault(p?=>request.Path.ToString().Equals(p.PathPattern,?StringComparison.OrdinalIgnoreCase)?&&?p.Method.ToUpper()?==?request.Method.ToUpper());if?(permission?==?null){permission?=permissions.FirstOrDefault(p?=>Regex.IsMatch(request.Path.ToString(),?p.PathPattern,?RegexOptions.IgnoreCase)?&&?p.Method.ToUpper()?==?request.Method.ToUpper());}if?(user.Identity?.IsAuthenticated?==?true){if?(!string.IsNullOrWhiteSpace(permission?.AllowedRoles)?&&!permission.AllowedRoles.Split(new[]?{?','?},?StringSplitOptions.RemoveEmptyEntries).Any(r?=>?user.IsInRole(r))){httpContext.Items.SetError(new?UnauthorizedError("forbidden,?have?no?permission"));return;}}else{if?(permission?!=?null?&&?string.IsNullOrWhiteSpace(permission.AllowedRoles)){}else{httpContext.Items.SetError(new?UnauthenticatedError("unauthorized,?need?login"));return;}}await?_next.Invoke(httpContext);} }

    Diff

    主要的區(qū)別在于 ocelot 中間件的變化,在之前的版本,ocelot 是自己的中間件,簽名是 Task Invoke(DownstreamContext context) 是 ocelot 自己的 DownstreamContext,在之后 ,Ocelot 為了和 asp.net core 中間件保持一樣的簽名,以更好的復(fù)用 asp.net core 中的中間件,更新了自己的中間件, ocelot 自己的 context 等信息現(xiàn)在放在了 HttpContext.Items 中,并通過一系列的擴(kuò)展方法來獲取和更新對(duì)應(yīng)的信息

    但是目前的實(shí)現(xiàn)并不能夠完全等同于 asp.net core 中間件,因?yàn)槿绻阆胍袛嗄骋粋€(gè)中間件的話現(xiàn)在大概是有問題的,因?yàn)楝F(xiàn)在 ocelot 中間件里的 HttpContext 并不是原始的 HttpContext ocelot 會(huì)在真正開始處理請(qǐng)求之前新建一個(gè) HttpContext 把基本的請(qǐng)求信息復(fù)制過去,主要實(shí)現(xiàn)代碼: https://github.com/ThreeMammals/Ocelot/blob/17.0.0/src/Ocelot/Multiplexer/MultiplexingMiddleware.cs

    如果想要在自定義中間件中實(shí)現(xiàn)中斷,需要使用 ocelot 的中間件,通過 SetError 來去處理而不要直接使用 httpContext.Response 去中斷請(qǐng)求

    API Diff

  • 中間件 Invoke 方法簽名,從原來的 Task Invoke(DownstreamContext context) 更新成 Task Invoke(HttpContext context)

  • SetPipelineError 不再是 OcelotMiddleware 中的一個(gè)方法,通過 httpContext.Items.SetError 方法來代替

  • 通過 httpContext.Items.DownstreamRoute() 來獲取當(dāng)前請(qǐng)求的 DownstreamRoute 信息

  • More

    除了中間件的變化,配置也發(fā)生了變化,原來的 ReRoute 也變成了 Route,升級(jí)的時(shí)候需要注意一下配置的變化,否則可能就會(huì) 404 了,在 17.0 之后,authorisation 更新成了 authorization, authorise 也更新成了 authorize

    更多更新可以參考 ocelot 的 PR changes 和文檔

    文中提到的示例在 Github 上可以獲取完整的代碼 https://github.com/WeihanLi/AspNetCorePlayground/tree/master/OcelotDemo

    Reference

    • https://github.com/ThreeMammals/Ocelot/compare/15.0.0...16.0.0

    • https://github.com/ThreeMammals/Ocelot/compare/16.0.0...17.0.0

    • https://github.com/WeihanLi/AspNetCorePlayground/tree/master/OcelotDemo

    • https://www.cnblogs.com/weihanli/p/custom-authentication-authorization-in-ocelot.html

    總結(jié)

    以上是生活随笔為你收集整理的ocelot 中间件的变化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。