asp.net core系列 50 Identity 授權(中)

来源:https://www.cnblogs.com/MrHSR/archive/2019/04/08/10654790.html
-Advertisement-
Play Games

1.5 基於策略的授權 在上篇中,已經講到了授權訪問(authorization)的四種方式。其中Razor Pages授權約定和簡單授權二種方式更像是身份認證(authentication) ,因為只要是合法用戶登錄就能訪問資源。 而角色授權和聲明授權二種方式是真正的授權訪問(authorizat ...


1.5 基於策略的授權

  在上篇中,已經講到了授權訪問(authorization)的四種方式。其中Razor Pages授權約定和簡單授權二種方式更像是身份認證(authentication) ,因為只要是合法用戶登錄就能訪問資源。 而角色授權和聲明授權二種方式是真正的授權訪問(authorization)。

  下麵繼續講authorization的第五種方式--策略授權。策略授權由一個或多個需求(也可以稱"要求")組成(需求:TRequirement)。它在程式啟動時註冊為授權服務配置的一部分。在ConfigureServices方法中註冊。

 

  (1) 註冊策略授權

    創建了一個名為"AtLeast21"的策略授權,這個策略的需求是最小年齡需求,策略通過參數對象(IAuthorizationRequirement)提供,它要求最低年齡是21歲。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

                services.AddAuthorization(options =>
                 {
                     options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
                    // MinimumAgeRequirement參數對象 實現了IAuthorizationRequirement
                     options.AddPolicy("AtLeast21", policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
                 });
}

  

  (2) 策略授權應用到mvc的控制器或Razor Pages

//用戶購買酒業務, 策略授權應用到控制器,要求用戶年齡不能低於21歲
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseController : Controller
{
    public IActionResult Index() => View();
}
//策略授權到razor pages的PageModel類
[Authorize(Policy = "AtLeast21")]
public class AlcoholPurchaseModel : PageModel
{
}

     在razor pages中,策略還可以應用到razor page授權約定中。

    public static PageConventionCollection AuthorizeFolder(this PageConventionCollection conventions, string folderPath, string policy);

 

  (3) Requirement策略授權需求

    策略授權需求實現IAuthorizationRequirement介面,用於策略需求對象參數傳遞。MinimumAgeRequirement就是一個需求參數對象。

using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public int MinimumAge { get; }

    public MinimumAgeRequirement(int minimumAge)
    {
        MinimumAge = minimumAge;
    }
}

 

  (4) 策略授權處理程式類

    授權處理程式負責評估要求的屬性(指策略授權邏輯處理,把當前用戶的年齡與策略要求年齡進行驗證)。 授權處理程式會針對提供的AuthorizationHandlerContext 來評估要求,確定是否允許訪問或拒絕。

         實現策略授權處理程式,需要繼承AuthorizationHandler<TRequirement>,其中TRequirement就是參數對象。另外,一個處理程式也可以通過實現 IAuthorizationHandler 來處理多個類型的要求。

    下麵是一對一關係的示例(一個Handler處理一個TRequirement對象),評估最低年齡要求:

   public class MinimumAgeHandler: AuthorizationHandler<MinimumAgeRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                        MinimumAgeRequirement requirement)
        {
            if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
                                            c.Issuer == "LOCAL AUTHORITY"))
            {
                //TODO: Use the following if targeting a version of
                //.NET Framework older than 4.6:
                //      return Task.FromResult(0);
                return Task.CompletedTask;
            }

            var dateOfBirth = Convert.ToDateTime(
                context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth &&
                                            c.Issuer == "LOCAL AUTHORITY").Value);

            int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
            if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
            {
                calculatedAge--;
            }

            if (calculatedAge >= requirement.MinimumAge)
            {
               //滿足的要求作為其唯一參數
                context.Succeed(requirement);
            }

            //TODO: Use the following if targeting a version of
            //.NET Framework older than 4.6:
            //      return Task.FromResult(0);
            return Task.CompletedTask;
        }
    }

     上面代碼是當前用戶主休是否有一個由已知的受信任頒發者(Issuer)頒發的出生日期聲明(ClaimTypes.DateOfBirth)。當前用戶缺少聲明時,無法進行授權,這種情況下會返回已完成的任務。如果存在聲明時,會計算用戶的年齡。 如果用戶滿足此要求所定義的最低年齡,則可以認為授權成功。 授權成功後,會調用 context.Succeed,使用滿足的要求作為其唯一參數。

    

  (5) 處理程式註入到服務集合,採用單例

    services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

    在UserClaim用戶聲明表中,保存一條符合該策略授權的數據,當啟動程式,訪問AlcoholPurchase資源時,進入授權處理程式MinimumAgeHandler中, 執行context.Succeed(requirement)後, 授權成功。

    

  

  1.5.1 多個需求使用一個處理程式

     下麵是多個需求(TRequirement)使用一個處理程式,Handler實現IAuthorizationHandler介面,下麵示例是一個對多關係的許可權處理程式,可以在其中處理三種不同類型的需求:

public class PermissionHandler : IAuthorizationHandler
{
    public Task HandleAsync(AuthorizationHandlerContext context)
    {
         //獲取策略中的多個需求,返回IEnumerable<IAuthorizationRequirement>類型
        var pendingRequirements = context.PendingRequirements.ToList();
         
        foreach (var requirement in pendingRequirements)
        {
            //讀取授權
            if (requirement is ReadPermission)
            {
                if (IsOwner(context.User, context.Resource) ||
                    IsSponsor(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
            //編輯和刪除授權
            else if (requirement is EditPermission ||
                     requirement is DeletePermission)
            {
                if (IsOwner(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }

     具體詳細代碼,查看官方示例, Github

  

  1.5.2 處理程式應返回什麼? (有三種返回)

                   (1) 處理程式通過調用 context.Succeed(IAuthorizationRequirement requirement) 並傳遞已成功驗證的要求來表示成功。

                   (2) 處理程式通常不需要處理失敗(顯示加context.Fail()),因為同一要求的其他處理程式(1.5.3)可能會成功。

                   (3) 若要保證授權失敗,即使其它要求處理程式會成功,也會失敗,請調用context.Fail();   

    

  1.5.3  一個需求應用在多個處理程式

     這裡授權處理正好與15.1相反,下麵這個示例是門禁卡授權策略需求, 你公司的門禁卡丟在家中,去公司後要求前臺給個臨時門禁卡來開門。這種情況下,只有一個需求,但有多個處理程式,每個處理程式針對單個要求進行檢查。

     //策略授權需求,這裡沒有參數需求, 參數是硬編碼在處理程式中
     public class BuildingEntryRequirement : IAuthorizationRequirement
      {
      }
//門禁卡處理程式
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   BuildingEntryRequirement requirement)
    {
            //需求參數硬編碼 BadgeId 
        if (context.User.HasClaim(c => c.Type == "BadgeId" &&
                                       c.Issuer == "http://microsoftsecurity"))
        {
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }
}
//臨時門禁卡處理程式
public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, 
                                                   BuildingEntryRequirement requirement)
    {
        //需求參數硬編碼 TemporaryBadgeId
        if (context.User.HasClaim(c => c.Type == "TemporaryBadgeId" &&
                                       c.Issuer == "https://microsoftsecurity"))
        {
            // We'd also check the expiration date on the sticker.
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }
}
      // 註冊策略 
       services.AddAuthorization(options =>
            {
                  options.AddPolicy("BadgeEntry", policy =>policy.Requirements.Add(new BuildingEntryRequirement()));           
           });
    // 註入服務
     services.AddSingleton<IAuthorizationHandler, BadgeEntryHandler>();
     services.AddSingleton<IAuthorizationHandler, TemporaryStickerHandler>();

    當[Authorize(Policy = " BadgeEntry ")]應用到控制器後,只要有一個處理程式成功,則策略授權成功。需要在UserClaim用戶聲明表中維護好ClaimType。

 

  1.5.4 使用 func 滿足策略

    有些情況下,策略很容易用代碼實現。 可以在通過 Func<AuthorizationHandlerContext, bool> 策略生成器配置策略時提供需要聲明 (RequireAssertion),例如上一個 BadgeEntryHandler 可以重寫,如下所示: 

    services.AddAuthorization(options =>
    {
       options.AddPolicy("BadgeEntry", policy =>
           policy.RequireAssertion(context =>
              context.User.HasClaim(c =>
                  (c.Type == "BadgeId" ||
                   c.Type == "TemporaryBadgeId") &&
                   c.Issuer == "https://microsoftsecurity")));
    }); 

      

  總結:通過這二篇,熟悉了授權的五種方式,包括: 

    Razor Pages授權約定
    簡單授權
    角色授權
    聲明授權
    策略授權

    其中聲明授權包含了角色授權,通過ClaimTypes.Role 可以在聲明中使用角色授權。

   public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"

 

 參考文獻

    基於策略的授權

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 在調用方法的時候我們需要對輸入參數進行驗證,譬如非空,只能數字類型等; 2. 一些參數驗證都是非常通用的,所以可以累積後續不斷完善; 3. 這種寫法源於之前很早看到一篇博客後續完善,具體地址忘記了,所以現在Github項目採用協議:MIT,非常抱歉; 4. GitHub地址: "MasterC ...
  • v4.2.4 更新內容:1.增加了對接阿裡物聯網平臺的服務。下載地址:官方下載 6. 增加與阿裡雲物聯網(IOT)對接服務,實現數據交互 6.1 概述 為了滿足業務系統數據上雲的要求,ServerSuperIO集成了對接阿裡雲物聯網的服務。企業級系統建設採用ServerSuperIO作為後臺服務,同 ...
  • 將主埠COM8拆分成 COM1和COM2兩個虛擬埠 COM8接收的消息會傳遞給COM1和COM2 SerialPort spSend;//spSend,spReceive用虛擬串口連接,它們之間可以相互傳輸數據。spSend發送數據 SerialPort spReceive; //spRecei ...
  • 相較於數據,圖表更能直觀的體現數據的變化趨勢。在數據表格中,同一數據值,可能同時代表不同的數據分類,表現在圖表中則是一個數據體現在多個數據分類標簽下。通常生成的圖表一般預設只有一種分類標簽,下麵的方法將通過編程的方式來介紹在Excel中如何來生成含多層分類標簽的圖表。 使用工具:Spire.XLS ...
  • 這是今天下午一個同事問我的問題,如何在靜態類中讀取json配置文件。我當時並沒有告訴他如何如何去做,辦法肯定是有,但是這種編程思維確實得改改了。靜態類、靜態方法不是面向對象編程的最佳實踐。.NET Core已經為了我們提供了一種通過Dependency Injection獲取配置文件的方法。作為開發 ...
  • 持續集成之應用k8s自動部署 Intro 上次我們提到了 "docker容器化及自動化部署" ,這僅僅適合個人項目或者開發環境部署,如果要部署到生產環境,必然就需要考慮很多因素,比如訪問量大瞭如何調整部署,如何更好的應對大併發的情況,如何不停機更新應用,如果想要將Docker應用於具體的業務實現,是 ...
  • 通過前面章節的學習,我們已經對微信的開發有了基本的掌握與熟悉,基本可以上手做複雜的應用了。本篇我們將詳細講解微信消息管理中普通消息的接收與處理。當普通微信用戶向公眾賬號發消息時,微信伺服器將POST消息的XML數據包到開發者填寫的URL上。接收普通消息微信官方文檔參考:[接收普通消息文檔API](... ...
  • 1,環境 .net framework4.7.2,Autofac,Autofac.Mvc5,sql server 2,動機 公司項目用的是ef,之前留下代碼的大哥,到處using,代碼沒有分層,連復用都麽的,真的是夠了。現在要重構原來的系統,本著高效、簡潔、高耦合性的原則採用autofac + da ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...