• 重新整理 .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接口,得到为:

    那么这样就在网关实现了身份签名和认证了。那么如果其他服务需要进行认证的话,那么可以添加相同的认证方式即可。

    细节篇介绍一下这个的源码。

    下一节跨域请求的安全问题。

  • 相关阅读:
    【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
    【Atcoer】ARC088 E
    【Atcoder】ARC088 D
    【CodeForces】671 D. Roads in Yusland
    【CodeForces】671 B. Robin Hood
    【CodeForces】671 C. Ultimate Weirdness of an Array
    【CodeForces】679 A. Bear and Prime 100
    【CodeForces】679 B. Bear and Tower of Cubes
    【BZOJ】3262: 陌上花开
    【CodeForces】899 F. Letters Removing
  • 原文地址:https://www.cnblogs.com/aoximin/p/14979788.html
Copyright © 2020-2023  润新知