欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

asp net core2.1如何使用jwt從原理到精通(二)

 更新時間:2018年11月01日 14:17:53   作者:roberg  
這篇文章主要給大家介紹了關(guān)于asp net core2.1如何使用jwt從原理到精通的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在aspnet core中,自定義jwt管道驗證

有了上一節(jié)的內(nèi)容作為基礎(chǔ),那這點也是非常容易的,關(guān)鍵點在中間件,只是把上一級在測試類中的自定義驗證放到中間件中來即可,

不過需要注意:中間件 的位置很重要,只有它后面的管道才會收到影響;

那我們先建一個自定義中間件類:(中間件的詳細(xì)內(nèi)容這里就不講了,大家可以參考官網(wǎng)和其他博文)

/// <summary>
 /// 自定義授權(quán)中間件
 /// </summary>
 public class JwtCustomerAuthorizeMiddleware
 {
  private readonly RequestDelegate next;

  public JwtCustomerAuthorizeMiddleware(RequestDelegate next, string secret, List<string> anonymousPathList)
  {
   #region 設(shè)置自定義jwt 的秘鑰
   if(!string.IsNullOrEmpty(secret))
   {
    TokenContext.securityKey = secret;
   }
   #endregion
   this.next = next;
   UserContext.AllowAnonymousPathList.AddRange(anonymousPathList);
  }

  public async Task Invoke(HttpContext context, UserContext userContext,IOptions<JwtOption> optionContainer)
  {
   if (userContext.IsAllowAnonymous(context.Request.Path))
   {
    await next(context);
    return;
   }

   var option = optionContainer.Value;

   #region 身份驗證,并設(shè)置用戶Ruser值
 
   var result = context.Request.Headers.TryGetValue("Authorization", out StringValues authStr);
   if (!result || string.IsNullOrEmpty(authStr.ToString()))
   {
    throw new UnauthorizedAccessException("未授權(quán)");
   }
   result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>
   {
    var success = true;
    //可以添加一些自定義驗證,用法參照測試用例
    //驗證是否包含aud 并等于 roberAudience
    success = success && payLoad["aud"]?.ToString() == option.Audience;
    if (success)
    {
     //設(shè)置Ruse值,把user信息放在payLoad中,(在獲取jwt的時候把當(dāng)前用戶存放在payLoad的ruser鍵中)
     //如果用戶信息比較多,建議放在緩存中,payLoad中存放緩存的Key值
     userContext.TryInit(payLoad["ruser"]?.ToString());
    }
    return success;
   });
   if (!result)
   {
    throw new UnauthorizedAccessException("未授權(quán)");
   }

   #endregion
   #region 權(quán)限驗證
   if (!userContext.Authorize(context.Request.Path))
   {
    throw new UnauthorizedAccessException("未授權(quán)");
   }
   #endregion

   await next(context);
  }
 }

上面這個中間件中有個UserContext上線文,這個類主要管理當(dāng)前用戶信息和權(quán)限,其他信息暫時不管;我們先看一下這個中間件的驗證流程如何:

該中間件主要是針對訪問的路徑進(jìn)行驗證,當(dāng)然你也可以針對其他信息進(jìn)行驗證,比如(控制器名稱,動作名稱,等)

  • 檢查當(dāng)前url是否可以匿名訪問,如果可以就直接通過,不做驗證了;如果不是可以匿名訪問的路徑,那就繼續(xù)
  • 獲取當(dāng)前http頭部攜帶的jwt(存放在頭部的 Authorization中);
  • 使用上一節(jié)的講的TokenContext做必須的驗證和自定義復(fù)雜驗證;
  • 獲取當(dāng)前訪問用戶信息,我們把用戶的基本信息放在payLoad["ruser"]中,請看代碼如何操作
  • 到這里為止,都是做的身份驗證,表明你是一個有身份的的人;接下來是做權(quán)限驗證,你是一個有身份的人,并不代表你是一個隨便到處訪問的人;你能訪問哪些url或者action,就要得到權(quán)限驗證的認(rèn)可
  • 我們把權(quán)限驗證放到 userContext.Authorize方法中(這里怎么操作,這里就不深入講解,基本原理是從數(shù)據(jù)庫或者緩存中獲取當(dāng)前用戶對應(yīng)的權(quán)限列表,也就是url列表,進(jìn)行對比);

自定義中間件使用jwt驗證就這些內(nèi)容,是不是感覺很清晰,很簡單,有木有;

中間已經(jīng)完成了,那接下來我們來使用它,我們再startup中的Configure方法中添加如下代碼

app.UseMiddleware<JwtCustomerAuthorizeMiddleware>(Configuration["JwtOption:SecurityKey"], new List<string>() { "/api/values/getjwt","/" });

當(dāng)然上面可匿名訪問的url也可以定義在appsetting.json文件中,可以自行嘗試

如何通過自定義策略形式實現(xiàn)自定義jwt驗證

創(chuàng)建自定義策略的詳細(xì)介紹可以參考官網(wǎng),這里就不詳細(xì)介紹,

首先我們上代碼,創(chuàng)建自定義策略非常重要的兩個類,如下:

public class CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>
 {
  /// <summary>
  /// 常用自定義驗證策略,模仿自定義中間件JwtCustomerauthorizeMiddleware的驗證范圍
  /// </summary>
  /// <param name="context"></param>
  /// <param name="requirement"></param>
  /// <returns></returns>
  protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CommonAuthorize requirement)
  {
   var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;
   var userContext = httpContext.RequestServices.GetService(typeof(UserContext)) as UserContext;

   var jwtOption = (httpContext.RequestServices.GetService(typeof(IOptions<JwtOption>)) as IOptions<JwtOption>).Value;

   #region 身份驗證,并設(shè)置用戶Ruser值

   var result = httpContext.Request.Headers.TryGetValue("Authorization", out StringValues authStr);
   if (!result || string.IsNullOrEmpty(authStr.ToString()))
   {
    return Task.CompletedTask;
   }
   result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>
   {
    var success = true;
    //可以添加一些自定義驗證,用法參照測試用例
    //驗證是否包含aud 并等于 roberAudience
    success = success && payLoad["aud"]?.ToString() == jwtOption.Audience;
    if (success)
    {
     //設(shè)置Ruse值,把user信息放在payLoad中,(在獲取jwt的時候把當(dāng)前用戶存放在payLoad的ruser鍵中)
     //如果用戶信息比較多,建議放在緩存中,payLoad中存放緩存的Key值
     userContext.TryInit(payLoad["ruser"]?.ToString());
    }
    return success;
   });
   if (!result)
   {
    return Task.CompletedTask;
   }

   #endregion
   #region 權(quán)限驗證
   if (!userContext.Authorize(httpContext.Request.Path))
   {
    return Task.CompletedTask;
   }
   #endregion

   context.Succeed(requirement);
   return Task.CompletedTask;
  }
 }
 public class CommonAuthorize: IAuthorizationRequirement
 {

 }

其中兩個重要的類是哪兩個呢?他們的作用又是什么呢?

1、CommonAuthorize: IAuthorizationRequirement,至于取什么名字,自己定義,但必須繼承IAuthorizationRequirement,這類主要是承載一些初始化值,讓后傳遞到Handler中去,給驗證做邏輯運算提供一些可靠的信息;我這里是空的;自己根據(jù)自身情況自己定義適當(dāng)?shù)膶傩宰鳛槌跏紨?shù)據(jù)的承載容器;

2、CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>這個是重點,承載了驗證的邏輯運算
需要重寫override Task HandleRequirementAsync方法,所有的邏輯都在該方法中,他的主要邏輯和上面的自定義中間件很相似,只少了上面的第一步;驗證流程如下:

  • 獲取當(dāng)前http頭部攜帶的jwt(存放在頭部的 Authorization中);
  • 使用上一節(jié)的講的TokenContext做必須的驗證和自定義復(fù)雜驗證;
  • 獲取當(dāng)前訪問用戶信息,我們把用戶的基本信息放在payLoad["ruser"中,請看代碼如何操作
  • 到這里為止,都是做的身份驗證,表明你是一個有身份的的人;接下來是做權(quán)限驗證,你是一個有身份的人,并不代表你是一個隨便到處訪問的人;你能訪問哪些url或者action,就要得到權(quán)限驗證的認(rèn)可
  • 我們把權(quán)限驗證放到 userContext.Authorize方法中(這里怎么操作,這里就不深入講解,基本原理是從數(shù)據(jù)庫或者緩存中獲取當(dāng)前用戶對應(yīng)的權(quán)限列表,也就是url列表,進(jìn)行對比);
    context.Succeed(requirement);是驗證成功,如果沒有這個,就默認(rèn)驗證失敗
    因為UserContext把負(fù)責(zé)了權(quán)限驗證,所以不會把流程搞得感覺很亂,并且可以重用,至于用那種形式驗證也很容易切換

3、是不是很簡單,和自定義管道驗證的的代碼幾乎一模一樣,

如何使用自定義定義策略呢?

1、在startup類中的ConfigureServices中加入如下代碼:

services.AddAuthorization(option =>
   {
    

    #region 自定義驗證策略
    option.AddPolicy("common", policy => policy.Requirements.Add(new CommonAuthorize()));
    #endregion


   }).AddAuthentication(option =>
   {
    option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
   }).AddJwtBearer(option =>
   {
    if (!string.IsNullOrEmpty(config["JwtOption:SecurityKey"]))
    {
     TokenContext.securityKey = config["JwtOption:SecurityKey"];
    }
    //設(shè)置需要驗證的項目
    option.TokenValidationParameters = new TokenValidationParameters
    {
     
     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenContext.securityKey))//拿到SecurityKey
    };
   });

   //自定義策略IOC添加
   
   services.AddSingleton<IAuthorizationHandler, CommonAuthorizeHandler>();

     以上代碼主要分3個部分

     1、添加上面自定義的策略,并取名;

     2、設(shè)置秘鑰,這個秘鑰就是上一節(jié)中生成jwt的秘鑰,必須要要一樣,否則是簽名不正確

     3、注入上面建立的一個重要類CommonAuthorizeHandler,如上面代碼

2、在startup類中的Configure中添加 app.UseAuthentication();

3、在需要驗證的Controller或者Action中加上[Authorize(Policy = "common")]屬性,看下圖:

到此為止你就可以使用自定義策略的驗證了;

 

使用管道和自定義策略兩種形式進(jìn)行驗證有什么區(qū)別呢?

從效果上看都是一樣的,稍微有點區(qū)別

  • 使用管道的方式,感覺方便點,清晰點
  • 使用自定義策略的方式,效率稍微高一點,畢竟不是所有的請求都會進(jìn)行是否可以匿名訪問運算和建立管道的消耗,只有加入Authorize屬性的Controller和Action的才會進(jìn)入;當(dāng)然這點損耗可以忽略不計,看自己的喜好;

至于你喜歡那種,就使用哪種吧,性能可以忽略不計;

不管使用哪種方式使用jwt作為身份和權(quán)限驗證是不是很簡單,關(guān)鍵這里也把權(quán)限驗證的邏輯抽出來了,這樣代碼就更清晰明了了;

至于Authorize的屬性形式,還有很多其他的策略,比如用戶、申明,角色等,可查看官網(wǎng)https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/?view=aspnetcore-2.0

下一章將講解 用戶,申明 ,角色的驗證,并這些怎么在自定義的驗證中實現(xiàn),以便大家對他有個清晰的對比

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • asp .net實現(xiàn)給圖片添加圖片水印方法示例

    asp .net實現(xiàn)給圖片添加圖片水印方法示例

    圖片上加水印相信每位程序員都會遇到這個需求,下面這篇文章主要給大家介紹了asp .net實現(xiàn)給圖片添加圖片水印的方法,文中給出了完整的實例代碼,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • .NET中l(wèi)ambda表達(dá)式合并問題及解決方法

    .NET中l(wèi)ambda表達(dá)式合并問題及解決方法

    這篇文章主要介紹了.net?lambda表達(dá)式合并問題,解決方法是自己構(gòu)造一個新的表達(dá)式,構(gòu)造表達(dá)式需要用到expression類,本文結(jié)合實例代碼給大家詳細(xì)介紹,需要的朋友可以參考下
    2022-10-10
  • C#中的Equals、RefrenceEquals和==的區(qū)別與聯(lián)系

    C#中的Equals、RefrenceEquals和==的區(qū)別與聯(lián)系

    C#中判斷兩個對象是否相等有Equals、RefrenceEquals和==三種,其中==為運算符,其它兩個為方法,而Equals又有兩種版本,一個是靜態(tài)的,一個是虛擬的,詳細(xì)了解可以參考本文
    2012-12-12
  • ASP.NET返回上一頁面的實現(xiàn)代碼

    ASP.NET返回上一頁面的實現(xiàn)代碼

    今天用ASP.NET做一個類似淘寶中的訂單管理系統(tǒng),遇到的問題:主界面通過一個超鏈接跳轉(zhuǎn)到子界面后,試了好長時間還是無法從子界面返回主界面。
    2011-04-04
  • Request.UrlReferrer中文亂碼解決方法

    Request.UrlReferrer中文亂碼解決方法

    參考了網(wǎng)絡(luò)大部分的解決方案,沒一個能搞定的,如果窮途末路,試試下面的方法:將獲得的前一頁面的URL分成兩段,后面的參數(shù)部分進(jìn)行編碼(直接對URL編碼是不行的),然后再組合一下就可以了,需要的朋友可以了解下
    2012-12-12
  • Asp.net基于ajax和jquery-ui實現(xiàn)進(jìn)度條

    Asp.net基于ajax和jquery-ui實現(xiàn)進(jìn)度條

    這篇文章主要介紹了Asp.net基于ajax和jquery-ui實現(xiàn)進(jìn)度條,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12
  • C#,winform,ShowDialog,子窗體向父窗體傳值

    C#,winform,ShowDialog,子窗體向父窗體傳值

    窗體的show方法,沒有給調(diào)用代碼任何通知,如果需要通知,使用showdialog是一種好的選擇。 在調(diào)用show方法后,show方法后面的代碼會立即執(zhí)行,
    2008-08-08
  • 如何在ASP.NET Core中使用HttpClientFactory

    如何在ASP.NET Core中使用HttpClientFactory

    這篇文章主要介紹了如何在ASP.NET Core中使用HttpClientFactory,幫助大家更好的理解和學(xué)習(xí)使用.net技術(shù),感興趣的朋友可以了解下
    2021-04-04
  • asp.net Urlrewriter在虛擬主機上的使用方法

    asp.net Urlrewriter在虛擬主機上的使用方法

    在網(wǎng)上看到,很多朋友在asp.net中做urlrewrite,用的是HttpHandle Server.Transfer的方法。其實這種方法是錯誤的。
    2009-12-12
  • 分享提高ASP.NET Web應(yīng)用性能的技巧

    分享提高ASP.NET Web應(yīng)用性能的技巧

    這篇文章主要為大家分享提高ASP.NET Web應(yīng)用性能的技巧和方法,感興趣的朋友可以參考一下
    2016-01-01

最新評論