• 我的第一个netcore2.2 api项目搭建(三)续


    上一章快速陈述了自定义验证功能添加的过程,我的第一个netcore2.2 api项目搭建(三)

    但是并没有真正的去实现,这一章将要实现验证功能的添加。

    这一章实现目标三:jwt认证授权添加

    在netcore2.2中,只要添加很简单的配置就能添加jwt功能了。至于jwt本身是啥大家自行去了解,这里不做多说了。。

    1.1添加JwtHelper类

    public class JwtHelper
        {
            public const string Audience = "JH.OPEMR.API";
            public const string Issuer = "all";
            public const string SigningKey = "my first security key";
    
            public static string CreateJwtToken(string uid, string uName, string sub)
            {
                var dateTime = DateTime.UtcNow;
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SigningKey));
    
                var tokenHandler = new JwtSecurityTokenHandler();
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new Claim[]
                   {
                        new Claim(JwtClaimTypes.Audience,Audience),
                        new Claim(JwtClaimTypes.Issuer,Issuer),
                        new Claim(JwtClaimTypes.Id, uid),
                        new Claim(JwtClaimTypes.Name, uName),
                        new Claim("Role", sub)//高亮,很重要
                   }),
                    Expires = dateTime.AddHours(0.5),
                    SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
                };
                var token = tokenHandler.CreateToken(tokenDescriptor);
                var tokenString = tokenHandler.WriteToken(token);
                return tokenString;
            }
        }

    这个类就一个方法,提供生成加密的jwt串

    1.2在Startup做配置:

    //注册默认认证方式,这里使用jwt方式
                services.AddAuthentication(x =>
                {
                    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(o =>
                   {
                       o.TokenValidationParameters = new TokenValidationParameters
                       {
                           RoleClaimType = JwtClaimTypes.Role,//这个很重要
    
                           ValidIssuer = JwtHelper.Issuer,
                           ValidAudience = JwtHelper.Audience,
                           IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtHelper.SigningKey))
    
                           /***********************************TokenValidationParameters的参数默认值***********************************/
                           // RequireSignedTokens = true,
                           // SaveSigninToken = false,
                           // ValidateActor = false,
                           // 将下面两个参数设置为false,可以不验证Issuer和Audience,但是不建议这样做。
                           // ValidateAudience = true,
                           // ValidateIssuer = true, 
                           // ValidateIssuerSigningKey = false,
                           // 是否要求Token的Claims中必须包含Expires
                           // RequireExpirationTime = true,
                           // 允许的服务器时间偏移量
                           // ClockSkew = TimeSpan.FromSeconds(300),
                           // 是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
                           // ValidateLifetime = true
                       };
                   });

    可以看出,JwtHelper里的几个变量在Startup中也使用了,这样就保证了配置的参数和生成jwt串的参数保持了一致,这样就能起到防伪作用了,不是千千万万个jwt串在咱系统都能通过,如果都通过了,那不是搞笑么。。。

    1.3启用验证

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
            //启用验证
                app.UseAuthentication();
    
                //启用验证中间件
                //app.UseMiddleware<MyAutoMiddleware>();
    
                //启用Swagger
                app.UseSwagger();
                app.UseSwaggerUI(options =>
                {
                    options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    
                });
    
                app.UseMvc();
            }

    在前一章中,咱们并没有调用app.UseAuthentication(),是因为上一章咱们自己启用了中间件,并没有启用2.2注入的验证方式。而这一章,咱们注入了jwt,就得调用这句话是执行验证授权了。一旦启用,jwt就会自行进行请求的验证功能,不需要咱们在写代码了。。。

    ok,F5运行

    可以看到,未验证,调用失败。。

    咱们先用postman调用login模拟登录,生成一个jwt串,代码很简单:

    /// <summary>
        /// Account 模块
        /// </summary>
        [Route("api/[controller]/[action]")]
        [ApiController]
        public class AccountController : ControllerBase
        {
            [HttpGet]
            public ActionResult<string> Login(long Uid, string UName, string Sub)
            {
                if (string.IsNullOrWhiteSpace(Uid.ToString()) || string.IsNullOrWhiteSpace(UName)) throw new Exception("填写正确用户");
    
                var tokenString = JwtHelper.CreateJwtToken(Uid.ToString(), UName, Sub);
    
                return tokenString;
            }
        }

    这里我们得到jwt字符串,将这个字符串添加到header中,再用postman调用get试试:

    Headers添加 Authorization ,值:Bearer +jwt串,在Bearer后有个空格记住。

    ok了,是不是很简单,到这里jwt简单的认证授权其实已经加完了,后面可以根据各种权限去维护就好了。。。

    至此,第三个目标完成!

     既然添加了认证授权,那么第二章swagger部分就得也加入该功能了,这个很简单,只要在swagger里做配置就ok了。

    //添加header身份验证信息
                    var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
                    options.AddSecurityRequirement(security);
                    options.AddSecurityDefinition("Bearer", new ApiKeyScheme
                    {
                        Description = "JWT授权(数据将在请求头中进行传输) 参数结构: "Authorization: Bearer {token}"",
                        Name = "Authorization",//jwt默认的参数名称
                        In = "header",
                        Type = "apiKey"
                    });

    F5运行,可以看见加了锁

    点击Authorize,然后配置下:

    再来调用get:

    调用成功,可以看到header发送了刚刚添加的jwt串。

    至此,整个netcore api项目简单搭建已经完成!

    不过,按这种验证写法,突然想到,如果前端被劫持了jwt串,然后其他应用在此jwt串有效期内利用该jwt串调用api,不是也能调通吗??如果这样,不是很危险吗,竟然被别人给瞎调用了,这里留下了深深的思考,不知道大家都是怎么做的。。知情者可否留下解决方式,膜拜!!!

  • 相关阅读:
    线性代数学习笔记
    机器学习基石笔记
    how to design Programs 学习笔记
    programming-languages学习笔记--第2部分
    P6859 蝴蝶与花 思维 + 数据结构优化
    P6429 [COCI2010-2011#6] STEP 线段树维护最长01
    P1637 三元上升子序列 树状数组优化DP
    线段树模板3.0 区间乘
    CodeForces Global Round 11 B. Chess Cheater 贪心,处理技巧
    CodeForces Global Round 11 A. Avoiding Zero 构造
  • 原文地址:https://www.cnblogs.com/sy-ds/p/10838223.html
Copyright © 2020-2023  润新知