主頁 > .NET開發 > 基于.NetCore3.1系列 —— 認證授權方案之授權初識

基于.NetCore3.1系列 —— 認證授權方案之授權初識

2020-09-11 17:31:15 .NET開發

1.前言

回顧:認證授權方案之JwtBearer認證

授權

在上一篇中,我們通過JwtBearer的方式認證,了解在認證時,都是基于Claim的,因此我們可以通過用戶令牌獲取到用戶的Claims,在授權程序中對這些Claims進行驗證,從而來判斷是否具有獲取或執行目標資源操作的權限,本章就來介紹一下 ASP.NET Core 的授權系統的簡單使用,

2.說明

授權與身份認證是相互獨立,但是,授權卻需要一種身份驗證機制,因此,身份驗證可以為當前用戶創建一個或多個標識,是確定用戶真實身份的程序,而授權是根據標識確定用戶可執行的操作的程序,其本質就是具有某種特性的用戶會有權限訪問某個資源或者執行某個操作,例如:一個擁有管理員身份的用戶有創建人員、洗掉人員、編輯人員和洗掉人員的操作權限,而一個非管理身份的用戶僅有讀取自己資訊的權限,

這時候,你可能會問,究竟怎樣特性的用戶可以被授權訪問某個資源或執行某個操作,由此我們引出了授權策略的方式,可以根據用戶擁有的角色,也可以根據用戶的職位,部門甚至是性別,年齡等等特性進行授權,

通過建立授權策略方式,檢驗認證的用戶所攜帶的身份宣告(ClaimsPrincipal物件)與授權策略是否一致,從而確定用戶可否執行操作,

授權

3.授權

3.1. 基于角色

3.1.1 添加角色

將角色賦予某個控制器或控制器內的操作,指定當前用戶必須是其角色才能訪問請求資源,

可以使用Authorize屬性的Roles特性指定所請求資源的角色,

例如:

  • 分配了“admin”角色用戶進行訪問操作
[Authorize(Roles ="admin")]
public class WeatherForecastController : ControllerBase
{

}
  • 以逗號分隔角色名來允行多個角色訪問操作
[Authorize(Roles ="admin,user")]
public class WeatherForecastController : ControllerBase
{ 


}

其中只要滿足admmin或者user其一就可以進行訪問,

  • 同時滿足指定的多個角色進行的訪問操作
[Authorize(Roles = "admin")]
[Authorize(Roles = "user")]
public class WeatherForecastController : ControllerBase
{ 
}

3.1.2 添加策略的角色

可以創建策略的方式進行訪問控制,在配置授權服務中添加注冊授權服務策略,

在Startup.cs檔案中,通過ConfigureServices()配置服務,創建一個允許具有admin角色的用戶才能進行訪問的策略

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加授權角色策略
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseRole", options => options.RequireRole("admin"));
        });
        //或者指定多個允許的角色
        //services.AddAuthorization(options =>
        // {
        //    options.AddPolicy("MoreBaseRole", options => options.RequireRole("admin","user"));
        // });
    }

在控制器方法使用特性Policy的屬性進行策略應用

    [Authorize(Policy = "BaseRole")]
    public class WeatherForecastController : ControllerBase
    {
    
    }

3.2. 基于宣告

3.2.1添加宣告

對當前用戶必須擁有的宣告,并將宣告賦予某個控制器或控制器內的操作,因此,指定宣告必須持有對應的值才能訪問請求資源,

宣告要求基于策略,所以必須進行構建一個表示宣告要求的策略,才能進行授權,

最簡單的型別宣告是將判斷宣告是否存在,而不檢查值,

可以創建策略的方式進行訪問控制,在配置授權服務中添加注冊授權服務策略,

在Startup.cs檔案中,通過ConfigureServices()配置服務,創建一個允許具有宣告的用戶才能進行訪問的策略

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加基于宣告的授權
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseClaims", options => options.RequireClaim("name"));
        });
    }

BaseClaims宣告策略會檢查name當前標識是否存在宣告,

在控制器方法使用特性Policy的屬性進行策略應用

    [Authorize(Policy = "BaseClaims")]
    public class WeatherForecastController : ControllerBase
    {
    
    }

但是,大多時候,我們需要宣告包含值,只有指定允許值的串列,才能授權成功,所以,可以添加指定值,

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加基于宣告的授權,指定允許值串列,
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseClaims", options => options.RequireClaim("name","i3yuan"));
        });
    }

3.3 基于策略

上面介紹的基于角色和基于宣告的授權,都使用了要求、要求處理程式和預配置的策略,這些在構建上提供了便捷,但是最終都是生成授權策略,ASP.NET Core,設計了另一種靈活的授權方式,一種更豐富的可重復使用的授權結構,基于策略的授權,同時這也是授權的核心,

這節會先講一下授權策略的應用,在下一節中,會對授權策略的核心進行一步步的詳解,

在上面我們簡單的介紹了基于策略的角色授權,但是這種方式無非基于角色或者宣告多一些,

因此,這里我們基于自定義策略授權的方式,實作授權,

自定義授權,就要我們自己寫策略提供器,自己根據不同的引數來生成不同的策略,重新實作策略的方式,策略要求由以下兩種元素組成:僅保留資料的要求類,以及對用戶驗證資料的授權處理程式,創建自定義要求,還可以進一步表達特定策略,

3.3.1. 定義權限策略PermissionRequirement

定義一個權限策略,這個策略并包含一些屬性,

public class PermissionRequirement: IAuthorizationRequirement
{
    public string _permissionName { get; }

    public PermissionRequirement(string PermissionName)
    {
        _permissionName = PermissionName;
    }
}

3.3.2. 再定義一個策略處理類

public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
    {
        var role = context.User.FindFirst(c => c.Type == ClaimTypes.Role);
        if (role != null)
        {
            var roleValue = https://www.cnblogs.com/i3yuan/p/role.Value;
            if (roleValue==requirement._permissionName)
            {
                context.Succeed(requirement);
            }
        }
        return Task.CompletedTask;

授權處理程式讀取與角色用戶關聯的宣告,并檢查自定義的角色,如果角色匹則成功,否則無法回傳成功,

這里的自定義宣告是寫固定了,但是也可以通過資料庫或外部服務的方式進行運行查詢獲取用戶相關角色資訊相對應的判斷條件,從而在處理程式中進行判斷處理,

授權處理程式呼叫方法 Succeed,同時傳遞當前要求,以通知此要求已成功得到驗證,如果沒有傳遞要求,處理程式無需執行任何操作,可以直接回傳內容,不過,如果處理程式要確定是否不符合要求(無論其他處理程式是否已成功驗證同一要求),將會對授權背景關系物件呼叫方法 Fail

3.3.3. 下面展示了如何將自定義要求添加到策略

(請注意,由于這是自定義要求,因此沒有擴展方法,而必須繼續處理策略物件的整個 Requirements 集合):

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //基于自定義策略授權
        services.AddAuthorization(options =>
        {
            options.AddPolicy("customizePermisson",
              policy => policy
                .Requirements
                .Add(new PermissionRequirement("admin")));
        });
        //此外,還需要在 IAuthorizationHandler 型別的范圍內向 DI 系統注冊新的處理程式:
        services.AddScoped<IAuthorizationHandler, PermissionRequirementHandler>();
        // 如前所述,要求可包含多個處理程式,如果為授權層的同一要求向 DI 系統注冊多個處理程式,有一個成功就足夠了,

    }

3.3.4. 應用自定義的策略的特性

指定當前用戶必須是應用對控制器或控制器內的操作,如

   [Authorize(Policy = "customizePermisson")]
    public class WeatherForecastController : ControllerBase
    { 
    }

4.場景

在上一篇認證授權方案之JwtBearer認證中,我們已經實作了獲取token的方式,這一次,我們實作一個以基于角色場景為例的認證授權,

在原來生成token的方式中,添加多一個宣告角色的Claim,如下:

new Claim(JwtClaimTypes.Role,"admin")

    [HttpGet]
    public IActionResult GetToken()
    {
        try
        {
            //定義發行人issuer
            string iss = "JWTBearer.Auth";
            //定義受眾人audience
            string aud = "api.auth";
            //定義許多種的宣告Claim,資訊存盤部分,Claims的物體一般包含用戶和一些元資料
            IEnumerable<Claim> claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Id,"1"),
                new Claim(JwtClaimTypes.Name,"i3yuan"),
                new Claim(JwtClaimTypes.Role,"admin"),
            };
            //notBefore  生效時間
            // long nbf =new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
            var nbf = DateTime.UtcNow;
            //expires   //過期時間
            // long Exp = new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds();
            var Exp = DateTime.UtcNow.AddSeconds(1000);
            //signingCredentials  簽名憑證
            string sign = "q2xiARx$4x3TKqBJ"; //SecurityKey 的長度必須 大于等于 16個字符
            var secret = Encoding.UTF8.GetBytes(sign);
            var key = new SymmetricSecurityKey(secret);
            var signcreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            //String issuer = default(String), String audience = default(String), IEnumerable<Claim> claims = null, Nullable<DateTime> notBefore = default(Nullable<DateTime>), Nullable<DateTime> expires = default(Nullable<DateTime>), SigningCredentials signingCredentials = null
            var jwt = new JwtSecurityToken(issuer: iss, audience: aud, claims:claims,notBefore:nbf,expires:Exp, signingCredentials: signcreds);
            var JwtHander = new JwtSecurityTokenHandler();
            var token = JwtHander.WriteToken(jwt);
            return Ok(new
            {
                access_token = token,
                token_type = "Bearer",
            });
        }
        catch (Exception ex)
        {
            throw;
        }
    }

對控制器或控制器內的操作,指定當前用戶必須是其角色才能訪問請求資源,如WeatherForecastController.cs

[ApiController]
[Route("[controller]")]
[Authorize(Roles ="admin")]
public class WeatherForecastController : ControllerBase
{ 
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

5.運行

5.1. 獲取token

分別獲取role為admin和role為user的情況下頒發的token,只有在角色為admin的情況下才能授權通過,

5.2. 授權資源介面訪問

在role為admin的情況下

授權

授權

在role為user的情況下

授權

授權

由上可知,只有在角色為admin的情況下,才能訪問目標資源進行操作,

6.總結

  1. 從上一篇的認證到這一篇的授權階段,簡單的介紹了Asp.net Core的認證授權系統,對授權有了初步的認識以及使用,對授權進行劃分為兩種,一種是基于角色的授權,但隨著角色的增加會對處理授權產生限制,不適合表達復雜的授權邏輯,另一種是基于策略的身份驗證,策略包含一系列基于宣告的要求,以及基于可從 HTTP 背景關系或外部源注入的其他任何資訊的自定義邏輯,這些要求各自與一個或多個處理程式相關聯,這些處理程式負責要求的實際計算,
  2. 可以發現,asp.net core提供的授權策略是一個非常強大豐富且靈活的認證授權方案,能夠滿足大部分的授權場景,
  3. 如果有不對的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學習,共同進步,
  4. 因此,在后續的篇章中,會繼續探索授權系統,對授權策略的核心進行一步步的詳解,
  5. 本示例原始碼地址

參考文獻檔案

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/6437.html

標籤:.NET Core

上一篇:ABP(ASP.NET Boilerplate Project)快速入門

下一篇:如何在 asp.net core 3.x 的 startup.cs 檔案中獲取注入的服務

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more