日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
聊聊在.Net5.0中自定義授權(quán)響應(yīng)

本文轉(zhuǎn)載自微信公眾號(hào)「DotNET技術(shù)圈」,作者Ben Foster 。轉(zhuǎn)載本文請(qǐng)聯(lián)系DotNET技術(shù)圈公眾號(hào)。

在 .NET 5.0 中自定義授權(quán)響應(yīng)

ASP.NET Core 授權(quán)框架中經(jīng)常要求的[1]一項(xiàng)功能是能夠在授權(quán)失敗時(shí)自定義 HTTP 響應(yīng)。

以前,唯一的方法是IAuthorizationService直接在您的控制器中(或通過(guò)過(guò)濾器)調(diào)用授權(quán)服務(wù) ,類(lèi)似于基于資源的授權(quán)方法[2]或?qū)崿F(xiàn)您自己的授權(quán)過(guò)濾器[3]。

從 .NET 5.0 開(kāi)始,您現(xiàn)在可以通過(guò)實(shí)現(xiàn)IAuthorizationMiddlewareResultHandler接口來(lái)自定義 HTTP 響應(yīng);當(dāng)授權(quán)失敗時(shí),授權(quán)框架會(huì)自動(dòng)調(diào)用中間件。

這是 記錄[4]在微軟文檔的網(wǎng)站,但根據(jù)我的具體使用情況我花了不少時(shí)間才找到。

問(wèn)題

我一直在采取措施將舊的 ASP.NET Web API 應(yīng)用程序移植到 .NET Core 5.0。此 API 具有分層 URI 結(jié)構(gòu),因此大多數(shù)端點(diǎn)將位于“站點(diǎn)”資源下,例如:

  • /sites
  • /sites/{siteId}
  • /sites/{siteId}/blog

為了驗(yàn)證用戶(hù)是否有權(quán)訪(fǎng)問(wèn)指定站點(diǎn),該應(yīng)用程序以前使用自定義操作過(guò)濾器來(lái)提取siteId路由參數(shù)并根據(jù)用戶(hù)的聲明對(duì)其進(jìn)行驗(yàn)證。遷移到 .NET 5.0 我想利用授權(quán)框架來(lái)實(shí)現(xiàn)這種基于資源的授權(quán),但同樣不想在每個(gè)控制器中復(fù)制這個(gè)邏輯。

我的解決方案是實(shí)現(xiàn)一個(gè)執(zhí)行類(lèi)似操作的授權(quán)處理程序,獲取siteId參數(shù)并驗(yàn)證用戶(hù)的訪(fǎng)問(wèn)權(quán)限:

 
 
 
  1. public class SiteAccessAuthorizationHandler : AuthorizationHandler 
  2.     private const string SiteIdRouteParameter = "siteId"; 
  3.     private readonly ILogger _logger; 
  4.  
  5.     public SiteAccessAuthorizationHandler(ILogger logger) 
  6.     { 
  7.         _logger = logger.NotNull(nameof(logger)); 
  8.     } 
  9.  
  10.     protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SiteAccessRequirement requirement) 
  11.     { 
  12.         context.NotNull(nameof(context)); 
  13.         requirement.NotNull(nameof(requirement)); 
  14.  
  15.         if (context.Resource is HttpContext httpContext 
  16.             && httpContext.GetRouteData().Values.TryGetValue(SiteIdRouteParameter, out object? routeValue) 
  17.             && routeValue is string siteId) 
  18.         { 
  19.             string qualifiedId = $"sites/{siteId}"; 
  20.             AccountPrincipal account = context.User.ToAccount(); 
  21.  
  22.             _logger.LogDebug("Validating access to Site {SiteId} from User {UserId}.", qualifiedId, account.GetAuthIdentifier()); 
  23.  
  24.             if (account.CanAccessSite(qualifiedId)) 
  25.             { 
  26.                 context.Succeed(requirement); 
  27.             } 
  28.             else 
  29.             { 
  30.                 _logger.LogWarning("Site validation failed. User {UserId} is not permitted to access {SiteId}.", account.GetAuthIdentifier(), qualifiedId); 
  31.             } 
  32.         } 
  33.  
  34.         return Task.CompletedTask; 
  35.     } 

然后將其注冊(cè)為授權(quán)策略的一部分:

 
 
 
  1. services.AddAuthorization(options => 
  2. {                 
  3.     options.FallbackPolicy = Policies.FallbackPolicy; 
  4.     options.AddPolicy("SiteAccess", Policies.SiteAccessPolicy); 
  5. }) 
  6.  
  7. public static AuthorizationPolicy SiteAccessPolicy => 
  8.     ConfigureDefaults(new AuthorizationPolicyBuilder()) 
  9.         .AddRequirements(new SiteAccessRequirement()) 
  10.         .Build(); 
  11.  
  12. private static AuthorizationPolicyBuilder ConfigureDefaults(AuthorizationPolicyBuilder builder) 
  13.     => builder.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) 
  14.         .RequireAuthenticatedUser() 
  15.         .RequireClaim(JwtClaimTypes.ClientId); 

并應(yīng)用于控制器和/或動(dòng)作:

 
 
 
  1. [Authorize(Policy = "SiteAccess")] 
  2. [HttpGet("{siteId}", Name = RouteNames.SiteRoute)] 
  3. public async Task GetSiteAsync(string siteId, CancellationToken cancellationToken) 
  4.     var site = await _session.LoadAsync($"sites/{siteId}", cancellationToken); 
  5.     return site is null ? NotFound() : Ok(Enrich(_mapper.Map(site), true)); 

當(dāng)我嘗試訪(fǎng)問(wèn)未映射到當(dāng)前用戶(hù)的站點(diǎn)時(shí),我會(huì)收到HTTP 403 - Forbidden響應(yīng)。

這樣雖然達(dá)到了保護(hù)站點(diǎn)資源的目的,但也存在泄露用戶(hù)無(wú)權(quán)訪(fǎng)問(wèn)的站點(diǎn)信息的弊端。因此最好返回一個(gè)HTTP 404 - Not Found響應(yīng)??紤]到該站點(diǎn)不存在于用戶(hù)的站點(diǎn)資源集合中,這在語(yǔ)義上也是有意義的。

如果您想知道為什么我不只是將用戶(hù)過(guò)濾器作為查詢(xún)的一部分,那是因?yàn)橛脩?hù)/帳戶(hù)與內(nèi)容域是分開(kāi)的,并且由于數(shù)據(jù)模型的設(shè)計(jì)以及我使用的事實(shí)鍵值存儲(chǔ),驗(yàn)證訪(fǎng)問(wèn)的責(zé)任轉(zhuǎn)移到應(yīng)用層。

解決方案

為了實(shí)現(xiàn)上述目標(biāo),我們可以使用 newIAuthorizationMiddlewareResultHandler并創(chuàng)建一個(gè)處理程序,當(dāng)由于我的站點(diǎn)訪(fǎng)問(wèn)要求未得到滿(mǎn)足而導(dǎo)致授權(quán)失敗時(shí),該處理程序會(huì)轉(zhuǎn)換 HTTP 響應(yīng):

 
 
 
  1. public class AuthorizationResultTransformer : IAuthorizationMiddlewareResultHandler 
  2.     private readonly IAuthorizationMiddlewareResultHandler _handler; 
  3.  
  4.     public AuthorizationResultTransformer() 
  5.     { 
  6.         _handler = new AuthorizationMiddlewareResultHandler(); 
  7.     } 
  8.  
  9.     public async Task HandleAsync( 
  10.         RequestDelegate requestDelegate, 
  11.         HttpContext httpContext, 
  12.         AuthorizationPolicy authorizationPolicy, 
  13.         PolicyAuthorizationResult policyAuthorizationResult) 
  14.     { 
  15.         if (policyAuthorizationResult.Forbidden && policyAuthorizationResult.AuthorizationFailure != null) 
  16.         { 
  17.             if (policyAuthorizationResult.AuthorizationFailure.FailedRequirements.Any(requirement => requirement is SiteAccessRequirement)) 
  18.             { 
  19.                 httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; 
  20.                 return; 
  21.             } 
  22.  
  23.             // Other transformations here 
  24.         } 
  25.  
  26.         await _handler.HandleAsync(requestDelegate, httpContext, authorizationPolicy, policyAuthorizationResult); 
  27.     } 

在上面的代碼中,我檢查授權(quán)失敗(結(jié)果是禁止)和失敗的要求,相應(yīng)地更改HTTP狀態(tài)代碼;否則我們通過(guò)調(diào)用內(nèi)置的AuthorizationMiddlewareResultHandler.

為了連接自定義處理程序,它在啟動(dòng)時(shí)注冊(cè):

 
 
 
  1. services.AddAuthorization(options => 
  2. {                 
  3.     options.FallbackPolicy = Policies.FallbackPolicy; 
  4.     options.AddPolicy("SiteAccess", Policies.SiteAccessPolicy); 
  5. }) 
  6. .AddSingleton(); 

References

[1] 經(jīng)常要求的: https://github.com/dotnet/aspnetcore/issues/4670

[2] 基于資源的授權(quán)方法: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased?view=aspnetcore-5.0

[3] 實(shí)現(xiàn)您自己的授權(quán)過(guò)濾器: https://ignas.me/tech/custom-unauthorized-response-body/

[4] 記錄: https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/customizingauthorizationmiddlewareresponse?view=aspnetcore-5.0


分享標(biāo)題:聊聊在.Net5.0中自定義授權(quán)響應(yīng)
瀏覽地址:http://m.5511xx.com/article/cohhddg.html