隐藏

.net core3.1项目引用JWT保护API接口

发布:2023/9/10 13:22:26作者:管理员 来源:本站 浏览次数:481

前言


在上一篇文章《.net core3.1项目部署到linux的docker》,向大家展示了一个简单的.net core api项目的部署过程,但是没有对接口的安全性过多的处理,相当于接口都是裸奔的情况,这是很危险的。所以我们对比进行升级一下,使用JWT来实现接口的认证。

什么是JWT


根据维基百科的定义,JSON WEB Token(JWT),是一种基于JSON的、用于在网络上声明某种主张的令牌(token),是目前最流行的接口认证方案。

简易JWT说明流程图


步骤说明:


   客户端发送用户名密码信息到认证服务器获取 token;

   客户端请求 API 获取数据时带上 token;

   服务器端验证 token,合法则返回正确的数据。


深入了解


有一个网站叫:https://jwt.io/ ,我们在这个站点上对 Jwt 产生的 token 做验证:

从上图可以看出 Jwt 生产的 token 由三个部分组成:


   Header(红色):头

   Playload(紫色):负载

   Verify Sigantuer(蓝色):签名


这三个部分由英文的点进行拼接,内容结构为:Header.Payload.Signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c


Header

头信息是一个json格式的数据


{

 "alg": "HS256",

 "typ": "JWT"

}


  


   alg:表示加密的算法

   typ:表示 token 的类型


Playload

Playload 是 token 的主体内容部分,我们可以用来传递一些信息给客户端,比如过期时间就是通过 Playload 来进行传递的。 但因为默认情况下 Playload 的数据是明文的,所以敏感信息不要放在这里。


Verify Sigantuer

Verify Sigantuer 是对前面两个部分的签名,防止数据篡改。

开始使用JWT


下面我演示的截图都是在vs2019上面的操作

第一步,添加JWT包的引用


在.net core API项目中添加Microsoft.AspNetCore.Authentication.JwtBearer 包的引用

第二步,修改 Starup


   在 ConfigureServices 方法中添加服务注册。


           // jwt 认证

           services.AddAuthentication(options =>

           {

               options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

               options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

               options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

           }).AddJwtBearer(options =>

           {

               options.SaveToken = true;

               options.RequireHttpsMetadata = false;

               options.TokenValidationParameters = new TokenValidationParameters()

               {

                   ValidateIssuer = true,

                   ValidateAudience = true,

                   ValidAudience = "https://blog.csdn.net/shaojiayong",

                   ValidIssuer = "https://blog.csdn.net/shaojiayong",

                   IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"))

               };

           });


  


   Configure 配置认证中间件


app.UseAuthentication();//认证中间件




第三步,创建一个token


   添加一个登录model命名为LoginInput


   public class LoginInput

   {

       public string Username { get; set; }

       public string Password { get; set; }

   }


  


   添加一个认证控制器命名为AuthenticateController


using System;

using System.Collections.Generic;

using System.IdentityModel.Tokens.Jwt;

using System.Linq;

using System.Security.Claims;

using System.Text;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Microsoft.IdentityModel.Logging;

using Microsoft.IdentityModel.Tokens;

using TestAPI.Model;


namespace TestAPI.Controllers

{

   [Route("api/[controller]")]

   [ApiController]

   public class AuthenticateController : ControllerBase

   {

       [HttpPost]

       [Route("login")]

       public IActionResult Login([FromBody] LoginInput input)

       {

           //从数据库验证用户名,密码

           //验证通过 否则 返回Unauthorized


           //创建claim

           var authClaims = new[] {

               new Claim(JwtRegisteredClaimNames.Sub,input.Username),

               new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())

           };

           IdentityModelEventSource.ShowPII = true;

           //签名秘钥 可以放到json文件中

           var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"));


           var token = new JwtSecurityToken(

                  issuer: "https://blog.csdn.net/shaojiayong",

                  audience: "https://blog.csdn.net/shaojiayong",

                  expires: DateTime.Now.AddHours(2),

                  claims: authClaims,

                  signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)

                  );


           //返回token和过期时间

           return Ok(new

           {

               token = new JwtSecurityTokenHandler().WriteToken(token),

               expiration = token.ValidTo

           });

       }

   }

}


 


第四步,控制器添加个Authorize标签


   [Authorize]

   [Route("api/[controller]")]

   [ApiController]

   public class ValuesController : ControllerBase