重新整理 .net core 實踐篇————網關中的身份簽名認證[三十七]


前言

簡單整理一下網關中的jwt,jwt用於授權認證的,其實關於認證授權這塊https://www.cnblogs.com/aoximin/p/12268520.html 這個鏈接的時候就已經寫了,當然只寫到了4節,后面有10節沒有寫,是相對復雜的場景,后續會補齊。

正文

jwt 是json web tokens,是一種支持前面的數據結構。

至於什么是jwt的話,https://www.jianshu.com/p/576dbf44b2ae 這里有人寫的比較好了。

然后前文也提及到為什么在網關做身份認證了,因為這樣就不需要專門調用另外一個服務來實現身份認證,身份認證授權可以在網關和所以微服務同時生效。

教程直接在.net core文檔里面搜索jwt即可查閱到。

那么就根據例子要演示一下:

首先加入對應的包:

在appsettings.json 中加入加密密鑰:

"SecurityKey": "asdfghjklqwertyuiopzxcvbnm"

然后注入服務:

var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]));
services.AddSingleton(securityKey);
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
	.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
	{

	}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
	{
		options.TokenValidationParameters = new TokenValidationParameters
		{
			ValidateIssuer = true,
			ValidateAudience = true,
			ValidateLifetime = true,
			ClockSkew = TimeSpan.FromSeconds(30),
			ValidateIssuerSigningKey = true,
			ValidAudience = "localhost",
			ValidIssuer = "localhost",
			IssuerSigningKey = securityKey
		};
	});

上面ValidateIssuer 、ValidateAudience 、ValidateLifetime 分別是驗證Issuer、Audience、Lifetime這三個的,其實Issuer、Audience驗證和不驗證的話影響不大,主要是因為jwt隨時可以解密出來,就是經過base64位的轉換。
加入中間件:

app.UseAuthentication();

app.UseAuthorization();

測試代碼:

[HttpGet]
public async Task<IActionResult> JwtLogin([FromServices]SymmetricSecurityKey securityKey,string userName)
{
	List<Claim> claims = new List<Claim>();
	claims.Add(new Claim("Name", userName));
	var creds = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256);
	var token = new JwtSecurityToken(
		 issuer:"localhost",
		 audience:"localhost",
		 claims:claims,
		 expires:DateTime.Now.AddMinutes(30),
		 signingCredentials:creds
		);
	var t = new JwtSecurityTokenHandler().WriteToken(token);
	return Content(t);
}

然后調用生成jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiMTIzIiwiZXhwIjoxNjI1NjE0NDkyLCJpc3MiOiJsb2NhbGhvc3QiLCJhdWQiOiJsb2NhbGhvc3QifQ.lQg70rMofgue9X_RQ1ft_NDmXyY2OJbTZodN4krVOUM

然后通過下面網址進行解密:

https://www.box3.cn/tools/jwt.html

然后來測試一下這個是否生效:

[ApiController]
[Route("[controller]")]
public class OrderController : Controller
{
	[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme+","+CookieAuthenticationDefaults.AuthenticationScheme)]
	public IActionResult oneApi()
	{
		return Content(User.FindFirst("name").Value);
	}
}

上面[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme+","+CookieAuthenticationDefaults.AuthenticationScheme)]的意思是可以通過jwt驗證也可以通過cookie來驗證。

為什么要這么寫呢?因為:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
	.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
	{

	}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options ....

上面寫了兩種方式,且AddCookie在前,那么如果只寫Authorize,那么默認是cookie,如果AuthenticationSchemes 為JwtBearerDefaults.AuthenticationScheme,那么只有jwt。

一般我們的項目中用jwt,但是因為有些網站剛開始的時候覺得方便用了cookie,后來因為有app接口,那么需要添加jwt,這里不是只app接口不能用cookie,而是不太方便。

那么效果如下:

可以看到傳遞了一個Authoization的參數,這個參數是約定參數,那么值就是Bearer加空格,然后后面接的就是jwt了,這些是約定。

那么返回了123,這個123就是我們jwt中Claim的key為name的值,調用就是User.FindFirst("name").Value,還是相當方便的。

當然我們也可以通過cookie來進行認證:

[HttpGet]
public async Task<IActionResult> CookieLogin(string userName)
{
	var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
	identity.AddClaim(new Claim("Name", userName));
	await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));
	return Content("login");
}

這樣把cookie 傳入到響應流中傳遞給前端。
然后訪問:http://localhost:5000/account?username=ao

可以看到有個cookie。

那么訪問一下剛才的oneApi接口,得到為:

那么這樣就在網關實現了身份簽名和認證了。那么如果其他服務需要進行認證的話,那么可以添加相同的認證方式即可。

細節篇介紹一下這個的源碼。

下一節跨域請求的安全問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM