c# dotnet core Jwtbearer Authentication实例
什么是JWT?
JWT(JSON Web Token), 顾名思义就是在Web上以JSON格式传输的Token
是HTTP提供了一套标准的身份验证框架:服务器可以用来针对客户端的请求发送质询(challenge),客户端根据质询提供身份验证凭证。质询与应答的工作流程如下:服务器端向客户端返回401(Unauthorized,未授权)状态码,并在WWW-Authenticate头中添加如何进行验证的信息,其中至少包含有一种质询方式。然后客户端可以在请求中添加Authorization头进行验证,其Value为身份验证的凭证信息
JWT的构成
JWT一般由三段构成,用"."号分隔开如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiaHgwMDIiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJhZG1pbiIsIm5iZiI6MTU2MDE0NzkzMiwiZXhwIjoxNTYwMTQ4NTMzLCJpc3MiOiJIeElzc3VlciIsImF1ZCI6Ikh4QXVkaWVuY2UifQ.b1Jcji5XTOkKtQ3xFV3vmAHqmz0wwhYNqH9-UjEtfzE
1、新建Jwtsetting.cs(jwt配置类,映射appsettings.json中Jwtsetting配置)和LoginViewModel.cs类(用户信息类)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Jwtsetting 2 { 3 /// <summary> 4 /// 证书颁发者 5 /// </summary> 6 public string Issuer { get; set; } 7 8 /// <summary> 9 /// 允许使用的角色 10 /// </summary> 11 public string Audience { get; set; } 12 13 /// <summary> 14 /// 加密字符串 15 /// </summary> 16 public string SecretKey { get; set; } 17 } 18 19 20 public class LoginViewModel 21 { 22 public string UserName { get; set; } = "hx002"; 23 public string Password { get; set; } = "hx123456"; 24 }
2、配置appsettings.json
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 { 2 "Logging": { 3 "LogLevel": { 4 "Default": "Warning" 5 } 6 }, 7 "JWTSetting": { 8 "Issuer": "Issuer",//发行者 9 "Audience": "Audience",//允许使用者(角色) 10 "SecretKey": "123213sadassdakey"//加密密匙字符串 11 }, 12 "AllowedHosts": "*" 13 }
3、Startup配置依赖注入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Startup 2 { 3 public Startup(IConfiguration configuration) 4 { 5 Configuration = configuration; 6 } 7 8 public IConfiguration Configuration { get; } 9 10 // This method gets called by the runtime. Use this method to add services to the container. 11 public void ConfigureServices(IServiceCollection services) 12 { 13 //获取配置参数 14 services.Configure<Jwtsetting>(Configuration.GetSection("JWTSetting")); 15 Jwtsetting setting = new Jwtsetting(); 16 Configuration.Bind("JWTSetting", setting); 17 services.AddAuthentication(option => 18 { 19 option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 20 option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 21 }).AddJwtBearer(config => 22 { 23 config.SecurityTokenValidators.Clear(); 24 config.SecurityTokenValidators.Add(new MyTokenValidate()); 25 config.Events = new JwtBearerEvents() 26 { 27 OnMessageReceived = context => 28 { 29 Microsoft.Extensions.Primitives.StringValues token = context.Request.Headers["myToken"];//myToken参数名称 30 context.Token = token.FirstOrDefault(); 31 return Task.CompletedTask; 32 } 33 }; 34 }); 35 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 36 37 } 38 39 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 40 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 41 { 42 if (env.IsDevelopment()) 43 { 44 app.UseDeveloperExceptionPage(); 45 } 46 else 47 { 48 // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 49 app.UseHsts(); 50 } 51 //启动验证 52 app.UseAuthentication(); 53 app.UseHttpsRedirection(); 54 app.UseMvc(); 55 } 56 }
4、新增LoginController,用于测试生成token
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 [Route("api/[controller]/[action]")] 2 [ApiController] 3 public class LoginController : ControllerBase 4 { 5 private Jwtsetting Setting; 6 public LoginController(IOptions<Jwtsetting> options) 7 { 8 Setting = options.Value; 9 } 10 [HttpGet] 11 public Object Login(string UserName = "002",string Password= "123456") 12 { 13 string tokenValue = string.Empty; 14 if (ModelState.IsValid) 15 { 16 Claim[] claims = new Claim[] { 17 new Claim(ClaimTypes.Name,UserName), 18 new Claim(ClaimTypes.Role, "admin") 19 }; 20 //获取加密Key 21 SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Setting.SecretKey)); 22 //加密方式 23 SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); 24 //生成token 25 JwtSecurityToken token = new JwtSecurityToken(Setting.Issuer, Setting.Audience, claims, DateTime.Now, DateTime.Now.AddMinutes(10), creds); 26 tokenValue = new JwtSecurityTokenHandler().WriteToken(token).ToString(); 27 28 } 29 return tokenValue; 30 } 31 }
5、新增MyTokenValidate,此类继承ISecurityTokenValidator,用于验证token是否正确
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class MyTokenValidate : ISecurityTokenValidator 2 { 3 public bool CanValidateToken => throw new NotImplementedException(); 4 5 public int MaximumTokenSizeInBytes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } 6 7 public bool CanReadToken(string securityToken) 8 { 9 return true; 10 } 11 12 /// <summary> 13 /// 验证token 14 /// </summary> 15 /// <param name="securityToken"></param> 16 /// <param name="validationParameters"></param> 17 /// <param name="validatedToken"></param> 18 /// <returns></returns> 19 public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) 20 { 21 ClaimsPrincipal principal; 22 try 23 { 24 validatedToken = null; 25 JwtSecurityToken token = new JwtSecurityToken(securityToken); 26 //获取到Token的一切信息 27 JwtPayload payload = token.Payload; 28 object role = (from t in payload where t.Key == ClaimTypes.Role select t.Value).FirstOrDefault(); 29 object name = (from t in payload where t.Key == ClaimTypes.Name select t.Value).FirstOrDefault(); 30 string issuer = token.Issuer; 31 SecurityKey key = token.SecurityKey; 32 System.Collections.Generic.IEnumerable<string> audience = token.Audiences; 33 ClaimsIdentity identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); 34 identity.AddClaim(new Claim(ClaimTypes.Name, name.ToString())); 35 identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, "admin")); 36 principal = new ClaimsPrincipal(identity); 37 } 38 catch (Exception) 39 { 40 41 throw; 42 } 43 44 return principal; 45 } 46 }
6、权限控制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 [Route("api/[controller]/[action]")] 2 [ApiController] 3 [Authorize(Roles = "admin")]