前言
在網上走一朝JWT,都會拿來和Session對比,這里不細說理論了,大家伙們百度找找,很多,很詳細;這里我們直接實操JWT在Asp.NetCore3.1中的應用;
走起
1. 建一個WebAPI項目(之前都截圖好多了,這里不截圖了);
2. Nuget包中安裝對應組件
3. 在Startup.cs文件中進行配置
ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); //獲取配置文件信息,因為是共用的,所以就統一放配置文件了 string secret = Configuration.GetValue<string>("JWT:Secrete");//秘鑰,這里的秘鑰長度不低於16 string issuer_z = Configuration.GetValue<string>("JWT:Issuer");//頒發方 string audience_z = Configuration.GetValue<string>("JWT:Audience");//接收方
//開始配置JWT services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { //是否驗證秘鑰 ValidateIssuerSigningKey = true, //秘鑰,記住一定要大於等於16位 IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)), //是否驗證頒發者 ValidateIssuer=true, //頒發者 ValidIssuer= issuer_z, //是否驗證接收方 ValidateAudience=true, ValidAudience= audience_z, //必須要有超時時間 RequireExpirationTime=true, //是否驗證超時,當設置exp和nbf時有效,同時啟用ClockSkew ValidateLifetime=true, //這是一個緩沖時間,系統默認是5分鍾,可設置;則Token有效時間就是過期時間+這個設置的緩沖時間 ClockSkew=TimeSpan.FromSeconds(50) }; }); }
Configure方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
4. 在對應Controller上或Action上加上Authorize標記
經過以上四步,基本上就用JWT對API進行認證保護,不信試一下,程序運行起來,Postman走起:
其他接口沒加Authorize特性的,正常訪問,如下:
加了特性的Action,訪問返回401,如下:
也就是說,加了Authorize特性的Action需要進行認證才能進行訪問;換句話來說,請求來的信息,需要服務端能解析驗證,JWT通過Token實現的;
生成Token
在UserController下增加一個獲取Token的方法,如下:
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.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; namespace JwtDemo.Controllers { [Route("[controller]/[action]")] [ApiController] public class UserController : ControllerBase { private readonly IConfiguration _configuration; public UserController(IConfiguration configuration) { _configuration = configuration; } [Authorize] public IActionResult UserInfo() { return Ok(new { Name = "Zoe", 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!="Zoe"&&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 = _configuration.GetValue<string>("JWT:Secrete"); string issuer_z = _configuration.GetValue<string>("JWT:Issuer"); string audience_z = _configuration.GetValue<string>("JWT:Audience"); //指定加密算法 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.AddHours(1),//有效時間 claims: claims ); //生成Token return new JwtSecurityTokenHandler().WriteToken(securityToken); } } public class User { public string LoginName{ get; set; } public string LoginPwd{ get; set; } } }
這樣Token就搞定了,項目運行起來,Postman訪問一下:
這樣我們就可以拿着這個Token進行保護API訪問了,前提是在有效期之內,生成的Token可以在JWT.io官網進行解析,如下:
Token在Postman中使用,把生成的Token靠到Token的位置,訪問保護的API,如下可以訪問了:
其實本質就是在請求頭Authorization中加上"Bearer 生成的Token",中間一定要有空格;前度調用的話也是在請求頭中添加就行;
總結
JWT使用是不是很簡單,輕松實現API的認證保護;下一遍我們說說JWT的權限驗證;
關注公眾號,每周更新至少兩篇關於.NetCore相關文章