當前位置:
首頁 > 知識 > Nancy基於JwtBearer認證的使用與實現

Nancy基於JwtBearer認證的使用與實現


簡單使用

第一步 , 用VS創建一個空的ASP.NET Core Web Application

Nancy基於JwtBearer認證的使用與實現

第二步 , 安裝相關的NuGet包

通過命令在Package Manager Console執行安裝下面的包,也可以用圖形界面來完成這一步操作。


Install-Package Microsoft.AspNetCore.Owin -Version 1.1.2

Install-Package Nancy -Pre

Install-Package Nancy.Authentication.JwtBearer

其中,Microsoft.AspNetCore.Owin和Nancy是基礎包,Nancy.Authentication.JwtBearer是等下要用到的組件包。

第三步 , 修改Startup,添加對Nancy的支持。


public class Startup

{

public void Configure(IApplicationBuilder app)

{

app.UseOwin(x=>x.UseNancy());

}

}

第四步 , 添加一個Module來驗證Nancy是否可以正常使用


public class MainModule : NancyModule

{

public MainModule()

{

Get("/",_=>

{

return "test";

});

}

}

正常情況下,這個時候運行項目是OK的,大致效果如下:

Nancy基於JwtBearer認證的使用與實現

下面一步就是添加一個Bootstrapper用於啟用JwtBearer驗證。


public class DemoBootstrapper : DefaultNancyBootstrapper

{

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)

{

base.ApplicationStartup(container, pipelines);

var keyByteArray = Encoding.ASCII.GetBytes("Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA==");

var signingKey = new SymmetricSecurityKey(keyByteArray);

var tokenValidationParameters = new TokenValidationParameters

{

// The signing key must match!

ValidateIssuerSigningKey = true,

IssuerSigningKey = signingKey,

// Validate the JWT Issuer (iss) claim

ValidateIssuer = true,

ValidIssuer = "http://www.cnblogs.com/catcher1994",

// Validate the JWT Audience (aud) claim

ValidateAudience = true,

ValidAudience = "Catcher Wong",

// Validate the token expiry

ValidateLifetime = true,

ClockSkew = TimeSpan.Zero

};

var configuration = new JwtBearerAuthenticationConfiguration

{

TokenValidationParameters = tokenValidationParameters

};

//enable the JwtBearer authentication

pipelines.EnableJwtBearerAuthentication(configuration);

}

}

如果使用過Nancy項目自帶的其他認證方式(Basic,Forms和Stateless),就會發現下面的才是關鍵,其他的只是用於JwtBearer認證的配置參數。


pipelines.EnableJwtBearerAuthentication(configuration);

下面簡單介紹一下配置參數。

配置參數主要有兩個,一個是TokenValidationParameters , 一個是Challenge 。

其中最主要的參數TokenValidationParameters,這是用來驗證客戶端傳過來的token是否合法的!

它位於Microsoft.IdentityModel.Tokens這個命名空間下面。

Challenge參數則是用於指定在Unauthorized時Http響應頭中WWW-Authenticate的值。它的默認值是Bearer


註:Challenge參數是從Microsoft.AspNetCore.Authentication.JwtBearer項目借鑒過來的。

到這裡, 我們已經完成了對JwtBearer認證的配置和啟用,下面還要驗證這個配置是否已經生效了!

創建一個新的Module,並在這個Module中使用RequiresAuthentication


public class SecurityModule : NancyModule

{

public SecurityModule() : base("/demo")

{

//important

this.RequiresAuthentication();

Get("/",_=>

{

return "JwtBearer authentication";

});

}

}

註: 這裡需要引用Nancy.Security這個命名空間

到這裡,驗證的代碼也已經寫好了,當我們訪問 http://yourdomain.com/demo 的時候

瀏覽器會提示我們The requested resource requires user authentication , 並且在響應頭中我們可以看到WWW-Authenticate對應的值是Bearer。

Nancy基於JwtBearer認證的使用與實現

我們創建一個合法的token值,然後通過Fiddler再發起一次請求,看看能否正常返回我們要的結果。

下面的代碼是生成一個測試token用的,其中的JwtSecurityToken對象應當與前面的配置一樣,才能確保token是有效的。


private string GetJwt()

{

var now = DateTime.UtcNow;

var claims = new Claim[]

{

new Claim(JwtRegisteredClaimNames.Sub, "demo"),

new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),

new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64)

};

//must the same as your setting in your boostrapper class

var symmetricKeyAsBase64 = "Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA==";

var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);

var signingKey = new SymmetricSecurityKey(keyByteArray);

var jwt = new JwtSecurityToken(

issuer: "http://www.cnblogs.com/catcher1994",

audience: "Catcher Wong",

claims: claims,

notBefore: now,

expires: now.Add(TimeSpan.FromMinutes(10)),

signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256));

var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

var response = new

{

access_token = encodedJwt,

expires_in = (int)TimeSpan.FromMinutes(10).TotalSeconds

};

return JsonConvert.SerializeObject(response, new JsonSerializerSettings { Formatting = Formatting.Indented });

}

通過Fiddler執行這個帶上了token的請求,大致結果如下 :

Nancy基於JwtBearer認證的使用與實現

可以看到成功取到了相應的內容!

然後是本次測試用的token值相關的信息:

Nancy基於JwtBearer認證的使用與實現


註:用Fiddler發起請求的時候,記得要在請求頭部加上Authorization,它的值是Bearer+空格+token值

到這裡,已經展示了如何使用這個JwtBearer認證的組件。

下面就介紹一下是怎麼實現的這個組件!


如何實現

在繼續下面的內容之前,我假設大家對Nancy的Pipelines有所了解,如果不了解的可以參考我以前的下面的鏈接

  • Nancy之Pipelines三兄弟(Before After OnError)

  • Nancy官方的Wike頁面。

因為其中的BeforePipeliine和AfterPipeline是實現這個認證組件的重要切入點。

另外,實現上還用了Nancy項目的代碼風格去編寫的代碼,所以你可能會發現與其自帶的Basic認證等寫法差不多。

從我們上面的例子使用來說明內部實現。

在上面例子的啟動器(Bootstrapper)中,我們有一行啟用JwtBearer認證的入口。這個入口是IPipelines的一個擴展方法。


/// <summary>

/// Module requires JwtBearer authentication

/// </summary>

/// <param name="pipeline">Bootstrapper to enable</param>

/// <param name="configuration">JwtBearer authentication configuration</param>

public static void EnableJwtBearerAuthentication(this IPipelines pipeline, JwtBearerAuthenticationConfiguration configuration)

{

JwtBearerAuthentication.Enable(pipeline, configuration);

}

在這個擴展方法中,調用了JwtBearerAuthentication這個靜態類的Enable方法,同時傳遞了當前的pipeline和JwtBearer認證的參數給這個方法。

下面是Enable方法的具體實現。


/// <summary>

/// Enables JwtBearer authentication for the application

/// </summary>

/// <param name="pipelines">Pipelines to add handlers to (usually "this")</param>

/// <param name="configuration">JwtBearer authentication configuration</param>

public static void Enable(IPipelines pipelines, JwtBearerAuthenticationConfiguration configuration)

{

if (pipelines == null)

{

throw new ArgumentNullException("pipelines");

}

if (configuration == null)

{

throw new ArgumentNullException("configuration");

}

pipelines.BeforeRequest.AddItemToStartOfPipeline(GetLoadAuthenticationHook(configuration));

pipelines.AfterRequest.AddItemToEndOfPipeline(GetAuthenticationPromptHook(configuration));

}

以BeforeRequest為例,我們把一個委託對象加入到了請求之前要處理的一個集合中去。這樣在每次請求之前都會去處理這個委託。

所以這裡有兩個部分。

  • 請求處理之前的token認證

  • 請求處理之後的響應

先來看看請求處理之前的token認證如何處理


private static Func<NancyContext, Response> GetLoadAuthenticationHook(JwtBearerAuthenticationConfiguration configuration)

{

return context =>

{

Validate(context,configuration);

return null;

};

}

這裡也是一個空殼,用於返回AddItemToStartOfPipeline方法需要的委託對象。

真正處理token的還是Validate這個方法。認證的處理還藉助了System.IdentityModel.Tokens.Jwt命名空間下面的JwtSecurityTokenHandler類。


private static void Validate(NancyContext context, JwtBearerAuthenticationConfiguration configuration)

{

//get the token from request header

var jwtToken = context.Request.Headers["Authorization"].FirstOrDefault() ?? string.Empty;

//whether the token value start with Bearer

if (jwtToken.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))

{

jwtToken = jwtToken.Substring("Bearer ".Length);

}

else

{

return;

}

//verify the token

if (!string.IsNullOrWhiteSpace(jwtToken))

{

try

{

SecurityToken validatedToken;

var tokenHandler = new JwtSecurityTokenHandler();

var validatedClaims = tokenHandler.ValidateToken(jwtToken, configuration.TokenValidationParameters, out validatedToken);

//var jwtSecurityToken = validatedToken as JwtSecurityToken;

context.CurrentUser = validatedClaims;

}

catch (Exception)

{

}

}

}

要對token進行驗證,首先要知道token是從那裡來的。常規情況下,都是將這個token放到請求頭的Authorization中。

所以第一步是要從請求頭中取出Authorization的值。這個值是必須以Bearer開頭的一個字元串。注意是Bearer加一個空格!

而我們要驗證的部分是去掉開頭這部分之後的內容。只需要構造一個JwtSecurityTokenHandler實例並調用這個實例的ValidateToken方法,並把要驗證的token值和我們的配置傳進去即可。

驗證成功後,最為主要的一步是將ValidateToken方法的返回值賦給當前Nancy上下文的CurrentUser!!

當驗證失敗的時候,ValidateToken方法會拋出一個異常,這裡只catch了這個異常,並沒有進行其他額外的處理。要處理無非也就是記錄日記,可以在這裡trace一下,配合Diagnostics的使用。但是目前並沒有這樣做。

到這裡,Before已經OK了,現在要處理After了。

當然對於After,也是只處理401(Unauthorized)的情況。主要是告訴客戶端 「當前請求的資源需要用戶認證」,並告訴客戶端當前請求的資源需要那種認證類型。


private static Action<NancyContext> GetAuthenticationPromptHook(JwtBearerAuthenticationConfiguration configuration)

{

return context =>

{

if (context.Response.StatusCode == HttpStatusCode.Unauthorized)

{

//add a response header

context.Response.WithHeader(JwtBearerDefaults.WWWAuthenticate, configuration.Challenge);

}

};

}

一個簡單的判斷加上響應頭部的處理。

到這裡,這個JwtBearer認證的組件已經ok了。

當然這裡只介紹了Pipeline的實現,還有一個是基於NancyModule的實現,本質還是pipeline的處理,所以這裡就不累贅了。


寫在最後

雖然簡單介紹了如何全使用和實現Nancy.Authentication.JwtBearer這個組件,相信大家對token(access_token)的使用是沒有太大疑問的。可能大家有疑問的是refresh_token的使用。

但是,對於refresh_token的使用,可以說因場景而異,也因人而異。只需要記住一點即可:refresh_token是用來換取一個新的並且可用的access_token。

作者:Catcher ( 黃文清 )

來源:http://catcher1994.cnblogs.com/

聲明: 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如果您發現博客中出現了錯誤,或者有更好的建議、想法,請及時與我聯繫!!如果想找我私下交流,可以私信或者加我QQ。

Nancy基於JwtBearer認證的使用與實現


更多優質內容推薦:

有錢任性,某公司豪擲500萬幫助20左右年輕人找工作,起因是做善良的人:

http://www.ujiuye.com/zt/jyfc/?wt.bd=zdy35845tt

學安卓,免學費!50天興趣課程等你來搶!

http://www.ujiuye.com/xydt/2017/13042.html?wt.bd=zdy35845tt

IT職業教育:http://xue.ujiuye.com/

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

SLAM中的優化理論(一)——線性最小二乘
乾貨:基於 Git Flow 的 Git 最佳實踐
基於.NET CORE微服務框架-談談surging的服務容錯降級
for循環問題

TAG:IT優就業 |

您可能感興趣

微軟發布Windows Defender System Guard運行時認證技術
嘲諷 Kanye West 的 T-Shirt 獲得本人認證,Stüssy London 開業單品公開| HB Daily
百佳泰協助Lenovo取得全球首台Thunderbolt 3的Titan Ridge Universal認證!
RED Hydrogen One手機獲WiFi認證
聯想Daydream一體機Mirage Solo通過3C認證
了解建築認證機構building certifier
易建科技eKing Cloud通過Kubernetes全球一致性認證
三星mini版Galaxy Home智能揚聲器獲FCC認證
Infortrend更新VMware認證,管理性與安全性雙劍出鞘
傳蘋果開放 USB Type-C轉Lightning 介面 MFi 認證
傳蘋果開放 USB Type-C 轉 Lightning 介面 MFi 認證
iPhone X Plus 獲EEC認證,iPhone X被迫跳樓價!
官方認證!Palace x Ralph Lauren聯名系列即將發布!
全新音頻與視頻技術更新!Trinnov Audio宣布將率先支持DTS:X Pro以及IMAX Enhanced認證!
Synopsys ICValidator獲得GLOBALFOUNDRIES 14LPP物理驗證Signoff認證
Meghan Markle 認證!加州品牌Birdies讓隨腳一穿的便鞋奢華升級
Anker氮化鎵PD充電器、MFI認證Type-c轉Lightning充電線在國內上架
谷歌嘗試讓Pixelbook獲得Windows 10認證
最新|全新音頻與視頻技術更新!Trinnov Audio宣布將率先支持DTS:X Pro以及IMAX Enhanced認證!
Mophie發布首款Qi認證的iPhone X充電保護殼