zoukankan      html  css  js  c++  java
  • .net core中使用jwt进行认证

    JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSAECDSA的公用/专用密钥对对JWT进行签名

    传统token

    当用登录成功后,服务端会根据用户的信息生成一个token,然后将token保存到redis中。当用户再次访问时会携带这个token访问,这时服务端会先去查一下redis,看有没有这个token或者是查看这个token是否过期,当redis中没有这个token时,登录验证失败,提示用户登录失败,否则直接放行。当然传统的token也有其一定的优势,比如说返回token能屏蔽用户的真实信息,临时且唯一。但当并发数量大的时候,这种模式存在的问题就是,用户一访问就去查redis,会增加redis的压力。

    JWT

    jwt通常由三部分组成分别是:

    • Header
    • Payload
    • Signature

      Header通常由两部分组成,令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。

    {
      "alg": "HS256",
      "typ": "JWT"
    }

      Payload 令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。有以下三种类型:注册声明,公共声明和私人声明。

      标准注册声明  

      iss:jwt的发行方
      sub:jwt声明的主题
      aud:jwt所面向的群体
      exp:到期时间
      nbf:(不早于)声明标识了JWT之前的时间不得接受处理

      公共声明

        使用JWT的人可以随意定义这些声明。主要包括用户的各种信息但要避免私密的信息

      私密声明

        私有声明是发布者和面向者所共同定义的声明

    {
      "phone": "1234567890",
      "name": "John Doe",
      "admin": true
    }

      Signature

    signature是一个签名信息,是对前两部分进行base64加密和secret一起进行组合加密,这里的secret就相当于一个加盐的操作

    例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret)

    最后生成的token就是下面的这种格式

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoid293byIsInN1YiI6InN1Yk5hbWUiLCJuYmYiOiIxNTk5MzY3NjUwIiwiZXhwIjoxNTk5MzY3OTUwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQ5OTk5IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo0OTk5OSJ9.cqn55T-VFKkKuG2hSdQ_WNqjBhYiK9o3LvK-E9a893Y

    通过jwt的工作原理,我们会发现jwt与传统的token相比,jwt不用去redis中查询对应的token信息而是通过定义的加密算法去进行校验,这一块算是对token的重大改进吧

    .Net Core中使用JWT

    1.通过nuget安装 Microsoft.AspNetCore.Authentication.JwtBearer

    2.在ConfigureServices中进行相应的注册

          //使用jwt进行认证
                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options => {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,  //是否验证超时  当设置exp和nbf时有效 
                            ValidateIssuerSigningKey = true,  ////是否验证密钥
                            ValidAudience = "http://localhost:49999",//Audience
                            ValidIssuer = "http://localhost:49998",//Issuer,这两项和登陆时颁发的一致
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("123456888jdijxhelloworldprefect")),     //拿到SecurityKey
                            //缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟                                                                                                            //注意这是缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟
                            ClockSkew = TimeSpan.FromMinutes(5)   //设置过期时间
                        };
                    });

    2.在Configure中添加认证授权中间件

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                app.UseRouting();
                app.UseAuthentication();   //认证
                app.UseAuthorization();    //授权
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }

    3.登录成功后生成token并返回客户端

           [HttpPost]
            public IActionResult Login(string username,string password)
            {
                var user = bll.GetUser(username, password);
                if (user != null)
                {
                    var claims = new[]
                   {
                       new Claim(ClaimTypes.Name,username),
                       new Claim(JwtRegisteredClaimNames.Sub, "subName"),
                       new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),    //NotBefore  token生效时间
                       new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMilliseconds(1)).ToUnixTimeSeconds()}") //Expiration  到期时间,按秒数计算
                    };
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("123456888jdijxhelloworldprefect"));   //key的长度要超过16个字符,不然回抛出异常
                    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                    var token = new JwtSecurityToken(
                       issuer: "http://localhost:49999",           //颁发token的web应用程序
                       audience: "http://localhost:49998",
                       claims: claims,
                       expires: DateTime.Now.AddMinutes(5),
                       signingCredentials: creds);
                    return Ok(new
                    {
                        token = new JwtSecurityTokenHandler().WriteToken(token),success=true,message="登录成功"
                    });
                }
                else
                {
                    return BadRequest(new { success = false, message = "登录失败,请重试" });
                }
            }
    用postman进行测试
    1.调用登录接口生成token

     2.不加token去访问保护的资源

     3.带上生成的token再次访问

     

  • 相关阅读:
    第一周实习工作总结
    service---七月十九号实验
    安卓常用链接
    Activity + 基础UI
    七月十四日安卓学习笔记
    安卓组件学习笔记
    剑指:数组中出现次数超过一半的数字
    剑指:二叉搜索树与双向链表
    剑指:二叉树中和为某一值的路径
    剑指:二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/HTLucky/p/13622328.html
Copyright © 2011-2022 走看看