WebApi必須保證安全,如今來添加JWT認證git
一、打開appsettings.json添加JWT認證的配置信息github
二、在項目根目錄下新建一個Models文件夾,添加一個JwtSettings.cs的實體json
1 namespace Dinner.WebApi.Models 2 { 3 public class JwtSettings 4 { 5 /// <summary> 6 /// 證書頒發者 7 /// </summary> 8 public string Issuer { get; set; } 9 10 /// <summary> 11 /// 容許使用的角色 12 /// </summary> 13 public string Audience { get; set; } 14 15 /// <summary> 16 /// 加密字符串 17 /// </summary> 18 public string SecretKey { get; set; } 19 } 20 }
三、Startup.cs文件中的ConfigureServices添加Jwt認證的代碼api
1 #region JWT認證 2 3 services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings")); 4 JwtSettings setting = new JwtSettings(); 5 //綁定配置文件信息到實體 6 Configuration.Bind("JwtSettings", setting); 7 //添加Jwt認證 8 services.AddAuthentication(option => 9 { 10 option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 11 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 12 }).AddJwtBearer(config => 13 { 14 config.TokenValidationParameters = new TokenValidationParameters 15 { 16 ValidAudience = setting.Audience, 17 ValidIssuer = setting.Issuer, 18 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey)) 19 }; 20 /* 21 config.SecurityTokenValidators.Clear(); 22 config.SecurityTokenValidators.Add(new MyTokenValidate()); 23 config.Events = new JwtBearerEvents() 24 { 25 OnMessageReceived = context => 26 { 27 var token = context.Request.Headers["myToken"]; 28 context.Token = token.FirstOrDefault(); 29 return Task.CompletedTask; 30 } 31 }; 32 */ 33 }); 34 35 #endregion
四、Startup.cs文件中的Configure添加Jwt認證的代碼安全
1 app.UseAuthentication();
五、基本配置都弄完了,如今是生成JwtToken,在ValuesController中添加一個生成Jwt的Actionapp
1 using Dinner.WebApi.Models; 2 using Microsoft.AspNetCore.Mvc; 3 using Microsoft.Extensions.Options; 4 using Microsoft.IdentityModel.Tokens; 5 using System; 6 using System.Collections.Generic; 7 using System.IdentityModel.Tokens.Jwt; 8 using System.Security.Claims; 9 using System.Text; 10 11 namespace Dinner.WebApi.Controllers 12 { 13 [Route("api/[controller]/[action]")] 14 public class ValuesController : Controller 15 { 16 private readonly JwtSettings setting; 17 public ValuesController(IOptions<JwtSettings> _setting) 18 { 19 setting = _setting.Value; 20 } 21 // GET api/values 22 [HttpGet] 23 public IEnumerable<string> Get() 24 { 25 return new string[] { "value1", "value2" }; 26 } 27 28 // GET api/values/5 29 [HttpGet("{id}")] 30 public string Get(int id) 31 { 32 return "value"; 33 } 34 35 // POST api/values 36 [HttpPost] 37 public void Post([FromBody]string value) 38 { 39 } 40 41 // PUT api/values/5 42 [HttpPut("{id}")] 43 public void Put(int id, [FromBody]string value) 44 { 45 } 46 47 // DELETE api/values/5 48 [HttpDelete("{id}")] 49 public void Delete(int id) 50 { 51 } 52 53 [HttpGet] 54 public IActionResult GetGenerateJWT() 55 { 56 try 57 { 58 var claims = new Claim[] 59 { 60 new Claim(ClaimTypes.Name, "wangshibang"), 61 new Claim(ClaimTypes.Role, "admin, Manage") 62 }; 63 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey)); 64 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); 65 var token = new JwtSecurityToken( 66 setting.Issuer, 67 setting.Audience, 68 claims, 69 DateTime.Now, 70 DateTime.Now.AddMinutes(30), 71 creds); 72 return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token) }); 73 } 74 catch (Exception ex) 75 { 76 return BadRequest(ex.Message); 77 } 78 79 } 80 } 81 }
這樣調用這個方法就會生成一個JwtToken,而後在UsersController上面添加一個[Authorize]的特性框架
上一篇咱們說過SwaggerUI配置的最後一句有一個options.OperationFilter<HttpHeaderOperation>(); 這裏咱們來看這個HttpHeaderOperationide
1 using Microsoft.AspNetCore.Authorization; 2 using Swashbuckle.AspNetCore.Swagger; 3 using Swashbuckle.AspNetCore.SwaggerGen; 4 using System.Collections.Generic; 5 using System.Linq; 6 7 namespace Dinner.WebApi 8 { 9 public class HttpHeaderOperation : IOperationFilter 10 { 11 public void Apply(Operation operation, OperationFilterContext context) 12 { 13 if (operation.Parameters == null) 14 { 15 operation.Parameters = new List<IParameter>(); 16 } 17 18 var actionAttrs = context.ApiDescription.ActionAttributes(); 19 20 var isAuthorized = actionAttrs.Any(a => a.GetType() == typeof(AuthorizeAttribute)); 21 22 if (isAuthorized == false) //提供action都沒有權限特性標記,檢查控制器有沒有 23 { 24 var controllerAttrs = context.ApiDescription.ControllerAttributes(); 25 26 isAuthorized = controllerAttrs.Any(a => a.GetType() == typeof(AuthorizeAttribute)); 27 } 28 29 var isAllowAnonymous = actionAttrs.Any(a => a.GetType() == typeof(AllowAnonymousAttribute)); 30 31 if (isAuthorized && isAllowAnonymous == false) 32 { 33 operation.Parameters.Add(new NonBodyParameter() 34 { 35 Name = "Authorization", //添加Authorization頭部參數 36 In = "header", 37 Type = "string", 38 Required = false 39 }); 40 } 41 } 42 } 43 }
這個代碼主要就是在swagger頁面添加了一個Authorization的頭部輸入框信息,以便來進行驗證測試
如今咱們基本工做都作好了,打開頁面測試吧,注意:傳入的Authorization參數必須是Bearer xxxxxxx的形式(xxxxxxx爲生成的Token)ui
他返回了Http200就是成功了
整個項目的框架基本算是搭建好了,這只是一個雛形而已,其實Authorize這一塊須要建一個BaseController繼承Controller再在BaseController上添加一個Authorize而後全部Controller繼承BaseController就不用一個一個的寫Authorize了,不須要驗證的加個AllowAnonymous就能夠了,其餘的直接擴展倉儲接口寫倉儲就能夠直接調用了
源碼地址: https://github.com/wangyulong0505/Dinner