JWT(core3.1版本测试)

什么是 JSON Web 令牌?

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

虽然 JWT 可以加密以在各方之间提供保密性,但我们将专注于签名令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌会向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是签署它的一方。

什么时候应该使用 JSON Web Tokens?

以下是 JSON Web 令牌有用的一些场景:

  • 授权:这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且能够在不同的域中轻松使用。

  • 信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。因为可以对 JWT 进行签名(例如,使用公钥/私钥对),所以您可以确定发件人就是他们所说的那个人。此外,由于使用标头和有效负载计算签名,您还可以验证内容没有被篡改。 

 

  1.创建一个webapi的项目(我创建的是core3.1的)

  2.首先引用2个包:①:Microsoft.AspNetCore.Authentication.JwtBearer;②:JWT

  3.在ConfigureServices 中配置JWT

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            #region  配置JWT
            var issurer = "Nuctech.CHN";//发行人
            var audience = "Api.Auth";//受众人
            var secret = "Nuc#techjjfa3bchn";//密钥

            /*
             一. TokenValidationParameters的参数默认值:
            1. ValidateAudience = true,  ----- 如果设置为false,则不验证Audience受众人
            2. ValidateIssuer = true ,   ----- 如果设置为false,则不验证Issuer发布人,但建议不建议这样设置
            3. ValidateIssuerSigningKey = false,
            4. ValidateLifetime = true,  ----- 是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
            5. RequireExpirationTime = true, ----- 是否要求Token的Claims中必须包含Expires
            6. ClockSkew = TimeSpan.FromSeconds(300), ----- 允许服务器时间偏移量300秒,即我们配置的过期时间加上这个允许偏移的时间值,才是真正过期的时间(过期时间 +偏移值)你也可以设置为0,ClockSkew = TimeSpan.Zero

             */
            //配置认证服务
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(y =>
            {
                y.TokenValidationParameters = new TokenValidationParameters
                {
                    //是否验证发行人
                    ValidateIssuer = true,
                    ValidIssuer = issurer,//发行人

                    //是否验证受众人
                    ValidateAudience = true,
                    ValidAudience = audience,

                    //是否验证密钥
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)),

                    ValidateLifetime = true,//验证过期时间
                    RequireExpirationTime = true //过期时间
                };
            });
            #endregion
        }

  4.在Configure 中写入(认证在前,授权在后,有顺序的)

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();//认证

            app.UseAuthorization();//授权

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

  5.创建一个 TestInfo 控制器,并写入如下代码

 [Route("api/[controller]")]
    [ApiController]
    public class TestInfo : ControllerBase
    {
        private readonly IConfiguration _configuration;
        public TestInfo(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        [Authorize]
        [HttpGet]
        public IActionResult UserInfo()
        {
            return Ok(new { Name = "chn", Age = 18 });
        }

        [HttpPost]
        public IActionResult GetToken(User u)
        {
            if (u == null || string.IsNullOrEmpty(u.LoginName) || string.IsNullOrEmpty(u.LoginPwd))
            {
                return Ok(new { code = -1, msg = "用户名或密码不能为空" });
            }
            //验证用户
            if (u.LoginName != "chn" && u.LoginPwd != "admin")
            {
                return Ok(new { code = -1, msg = "用户名或密码错误" });
            }
            //验证成功,构建Token
            string strToken = GenerateToken(u);
            //返回信息
            return Ok(new { code = 1, msg = "Success", data = new { LoginName = u.LoginName, Token = strToken, Expire = 3600, TokenType = JwtBearerDefaults.AuthenticationScheme } });
        }

        private string GenerateToken(User u)
        {
            //这里也是从配置文件读取的,和上面读取的一致,否则开启对应验证的话会不通过
            string secret = "Nuc#techjjfa3bchn";
            string issuer_z = "Nuctech.CHN";
            string audience_z = "Api.Auth";
            //指定加密算法
            var securityKey = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)), SecurityAlgorithms.HmacSha256);
            //可以在Token里增加信息,但这里不要加私密信息,比如密码等这种数据
            var claims = new Claim[] { new Claim("UserName", u.LoginName) };

            //组装数据
            SecurityToken securityToken = new JwtSecurityToken(
                  issuer: issuer_z,//颁发者
                  audience: audience_z,//接收者
                  signingCredentials: securityKey,//组装的秘钥

                  expires: DateTime.Now.AddSeconds(30),//有效时间
                  claims: claims
                );
            //生成Token
            return new JwtSecurityTokenHandler().WriteToken(securityToken);
        }
    }

    public class User
    {
        public string LoginName { get; set; }
        public string LoginPwd { get; set; }
    }

  6.启动程序,利用postman工具进行测试

  先拿到token,如下图:

  然后再把token复制到 get请求中

  

 

   总结:如果没有token直接请求get接口,会报401的错!!!

posted on 2022-06-22 16:40  泰坦尼克号上的活龙虾  阅读(217)  评论(0)    收藏  举报

导航