這是第二部:實現NetCore上的WebApi使用JWT認證json
一、NetCore新建一個WebApi的項目api
二、打開AppSettings.json,添加Jwt的信息,這裏爲了演示而已app
{ "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } }, "JwtSettings": { "Issuer": "XXX", "Audience": "XXXX", "SecretKey": "To live is to change the world!" } }
三、Models下新建兩個類,一個用於登陸,一個用於獲取配置文件中的值ide
1 namespace NerCoreJwt.Models 2 { 3 public class LoginViewModel 4 { 5 public string UserName { get; set; } = "wangshibang"; 6 7 public string Password { get; set; } = "123456"; 8 } 9 }
1 namespace NerCoreJwt.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 21 }
四、新建一個Controller,用來寫登陸後生成Token邏輯ui
1 using Microsoft.AspNetCore.Mvc; 2 using Microsoft.Extensions.Options; 3 using Microsoft.IdentityModel.Tokens; 4 using NerCoreJwt.Models; 5 using System; 6 using System.IdentityModel.Tokens.Jwt; 7 using System.Security.Claims; 8 using System.Text; 9 10 namespace NerCoreJwt.Controllers 11 { 12 [Route("api/[controller]/[action]")] 13 public class AuthorizeController : Controller 14 { 15 private JwtSettings setting; 16 public AuthorizeController(IOptions<JwtSettings> options) 17 { 18 setting = options.Value; 19 } 20 21 [HttpPost] 22 public IActionResult Login(LoginViewModel login) 23 { 24 if (ModelState.IsValid) 25 { 26 if (login.UserName == "wangshibang" && login.Password == "123456") 27 { 28 var claims = new Claim[] { 29 new Claim(ClaimTypes.Name, login.UserName), 30 new Claim(ClaimTypes.Role, "admin, Manage") 31 }; 32 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey)); 33 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); 34 var token = new JwtSecurityToken( 35 setting.Issuer, 36 setting.Audience, 37 claims, 38 DateTime.Now, 39 DateTime.Now.AddMinutes(30), 40 creds); 41 return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token) }); 42 } 43 } 44 return BadRequest(); 45 } 46 47 [HttpGet] 48 public IActionResult NoValidate() 49 { 50 return Ok(); 51 } 52 } 53 }
五、StartUp類裏面添加從Configure<JwtSettings>中獲取Section纔可使用IOptions獲取裏面的內容,爲了省事就所有貼出來了this
1 using Microsoft.AspNetCore.Authentication.JwtBearer; 2 using Microsoft.AspNetCore.Builder; 3 using Microsoft.AspNetCore.Hosting; 4 using Microsoft.Extensions.Configuration; 5 using Microsoft.Extensions.DependencyInjection; 6 using NerCoreJwt.Models; 7 using System.Linq; 8 using System.Threading.Tasks; 9 10 namespace NerCoreJwt 11 { 12 public class Startup 13 { 14 public Startup(IConfiguration configuration) 15 { 16 Configuration = configuration; 17 } 18 19 public IConfiguration Configuration { get; } 20 21 // This method gets called by the runtime. Use this method to add services to the container. 22 public void ConfigureServices(IServiceCollection services) 23 { 24 services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings")); 25 JwtSettings setting = new JwtSettings(); 26 Configuration.Bind("JwtSettings", setting); 27 services.AddAuthentication(option => 28 { 29 option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 30 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 31 }).AddJwtBearer(config => 32 { 33 /* 34 config.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters 35 { 36 ValidAudience = setting.Audience, 37 ValidIssuer = setting.Issuer, 38 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey)) 39 }; 40 */ 41 config.SecurityTokenValidators.Clear(); 42 config.SecurityTokenValidators.Add(new MyTokenValidate()); 43 config.Events = new JwtBearerEvents() 44 { 45 OnMessageReceived = context => 46 { 47 var token = context.Request.Headers["myToken"]; 48 context.Token = token.FirstOrDefault(); 49 return Task.CompletedTask; 50 } 51 52 }; 53 }); 54 55 services.AddMvc(); 56 } 57 58 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 59 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 60 { 61 if (env.IsDevelopment()) 62 { 63 app.UseDeveloperExceptionPage(); 64 } 65 app.UseAuthentication(); 66 app.UseMvc(); 67 } 68 } 69 }
六、Token生成了,能夠用PostMan調用接口試試,把生成的Token粘到jwt.io官網看看裏面的信息加密
下面咱們來進行受權spa
七、爲了自定義受權方法,咱們須要新建一個類,繼承自ISecurityTokenValidator接口3d
1 using Microsoft.AspNetCore.Authentication.JwtBearer; 2 using Microsoft.IdentityModel.Tokens; 3 using System.IdentityModel.Tokens.Jwt; 4 using System.Linq; 5 using System.Security.Claims; 6 7 namespace NerCoreJwt 8 { 9 public class MyTokenValidate : ISecurityTokenValidator 10 { 11 public bool CanValidateToken => true; 12 13 public int MaximumTokenSizeInBytes { get ; set ; } 14 15 public bool CanReadToken(string securityToken) 16 { 17 return true; 18 } 19 20 public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) 21 { 22 ClaimsPrincipal principal; 23 try 24 { 25 validatedToken = null; 26 //這裏須要驗證生成的Token 27 /* 28 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoid2FuZ3NoaWJhbmciLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJhZG1pbiwgTWFuYWdlIiwibmJmIjoxNTIyOTI0MDgxLCJleHAiOjE1MjI5MjU4ODEsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCJ9.fa0jDYt_MqHFcwQfsMS30eCsjEwQt_uiv96bGtMQJBE 29 */ 30 var token = new JwtSecurityToken(securityToken); 31 //獲取到Token的一切信息 32 var payload = token.Payload; 33 var role = (from t in payload where t.Key == ClaimTypes.Role select t.Value).FirstOrDefault(); 34 var name = (from t in payload where t.Key == ClaimTypes.Name select t.Value).FirstOrDefault(); 35 var issuer = token.Issuer; 36 var key = token.SecurityKey; 37 var audience = token.Audiences; 38 var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); 39 identity.AddClaim(new Claim(ClaimTypes.Name, name.ToString())); 40 identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, "admin")); 41 principal = new ClaimsPrincipal(identity); 42 } 43 catch 44 { 45 validatedToken = null;48 principal = null; 49 } 50 return principal; 51 } 52 } 53 }
八、而後註釋掉上面代碼我註冊的部分,由於這是原生的Authorize驗證特性,添加後面的自定義驗證邏輯code
九、在接口上面添加Authorize特性,用PostMan調用接口傳入生成的Token,設置斷點看看效果吧
1 using Microsoft.AspNetCore.Authorization; 2 using Microsoft.AspNetCore.Mvc; 3 using System.Collections.Generic; 4 5 namespace NerCoreJwt.Controllers 6 { 7 [Route("api/[controller]")] 8 public class ValuesController : Controller 9 { 10 // GET api/values 11 [Authorize(Roles = "admin")] 12 [HttpGet] 13 public IEnumerable<string> Get() 14 { 15 return new string[] { "value1", "value2" }; 16 } 17 18 // GET api/values/5 19 [HttpGet("{id}")] 20 public string Get(int id) 21 { 22 return "value"; 23 } 24 25 // POST api/values 26 [HttpPost] 27 public void Post([FromBody]string value) 28 { 29 } 30 31 // PUT api/values/5 32 [HttpPut("{id}")] 33 public void Put(int id, [FromBody]string value) 34 { 35 } 36 37 // DELETE api/values/5 38 [HttpDelete("{id}")] 39 public void Delete(int id) 40 { 41 } 42 } 43 }