.Net Core Jwt鉴权授权

  • .Net Core Jwt鉴权授权已关闭评论
  • 189 次浏览
  • A+
所属分类:.NET技术
摘要

验证的那几步顺序可以直接在自定义验证中验证
添加JWT验证读取配置文件添加Swagger支持,api右上角可以写Token

简介

  • Jwt分为三段 通过远点分割
  1. header => 描述这个token加密方式
  2. PlayLoad => 有效载荷,用户信息+自定义Claims信息Verify
  3. Signature => 签名, (头部信息base64处理,有效载荷base64处理) + 密钥
  • 示例 :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJFeHRlbmRlZDEiOiLml6Dkv6Hmga8iLCJFeHRlbmRlZDIiOiIiLCJFeHRlbmRlZDMiOiIiLCJFeHRlbmRlZDQiOiIiLCJFeHRlbmRlZDUiOiIiLCIxIjoi57O757uf566h55CG5ZGYIiwiMiI6IueUqOaIt-euoeeQhuWRmCIsImV4cCI6MTY4ODkwMTA2NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDg4IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo1MDg4In0.7J1J7yWj4ELHJZIwLKnT4RgcMu3rGAX5ACBFfCS0LWM 

基于.Net Core 验证方式

  1. 生成jwtToken
  2. 标记[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
  3. 验证 Issuer
  4. 验证 Audience
  5. 验证 SecurityKey
  6. 验证自定义验证
  7. 验证完成可以正常访问接口

验证的那几步顺序可以直接在自定义验证中验证

Jwt获取Token

引入三方包

<ItemGroup>     <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.31.0" />     <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" /> </ItemGroup> 

生成Token

 using Microsoft.IdentityModel.Tokens; using Programming.DotNetCore.Function.Entity.Jwt; using Programming.DotNetCore.Function.Interface.PasswordService; using Programming.DotNetCore.Function.Password.Entity; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text;  namespace Programming.DotNetCore.Function.Password {     public class JwtServices : IPassWordService     {         public string GetToken(UserInfo user,JwtConfig jwtConfig)         {             List<Claim> claims = new List<Claim>             {                 new Claim(ClaimTypes.Name, user.UserName ?? ""),                 new Claim("Extended1", user.Extended1 ?? ""),                 new Claim("Extended2", user.Extended2 ?? ""),                 new Claim("Extended3", user.Extended3 ?? ""),                 new Claim("Extended4", user.Extended4 ?? ""),                 new Claim("Extended5", user.Extended5 ?? ""),             };             if (user.Role is not null)             {                 foreach (var item in user.Role)                 {                     claims.Add(new Claim(item.Id.ToString(), item.Role));                 }             }             if(jwtConfig.SecurityKey == null)             {                 throw new Exception("JwtConfig.SecurityKey 不能为空");             }             SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey));             SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);             JwtSecurityToken token = new JwtSecurityToken(                 issuer:jwtConfig.Issuer,                 audience:jwtConfig.Audience,                 claims:claims,                 expires: DateTime.UtcNow.AddMinutes(jwtConfig.ExpiresMinutes),                 signingCredentials:creds             );             string resultToken = new JwtSecurityTokenHandler().WriteToken(token);             return resultToken;         }     } } 

UserInfo

namespace Programming.DotNetCore.Function.Password.Entity {     public class UserInfo     {         public string? UserName { get; set; }         public List<RoleInfo>? Role { get; set; }         public string? Extended1 { get; set; }         public string? Extended2 { get; set; }         public string? Extended3 { get; set; }         public string? Extended4 { get; set; }         public string? Extended5 { get; set; }     } } 

JwtConfig

namespace Programming.DotNetCore.Function.Entity.Jwt {     public class JwtConfig     {         public string? Audience { get; set; }         public string? Issuer { get; set; }         public string? SecurityKey { get; set; }         public int ExpiresMinutes { get; set; }     } } 

WebApi测试(获取Token)

Program.cs

//读取Jwt配置 builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("JwtTokenOptions")); 

appsetting.json

{   "JwtTokenOptions": {     "Issuer": "http://localhost:5088",     "Audience": "http://localhost:5088",     "SecurityKey": "kq4DY5N1eFJhscOkI7Zp4Nd0WNy9d9AEsN6Yjgdv9OxLyol66tzGBKT_7vwolN7GZ8EDwqJBwccjDJfb81ws5s3sbbP5wUzQ3-PcTSsD-Rueiu2rsOUZwg_NR3RBCwmtouV-832YV2trCjNTawLB1z0LMukWGFNaAJVZ8WdQcrYn6a0ko5oVhZqaHBgsCLEGiqPtoFsiCcrJTz1IvXHk9_cDSr2hwEmSl18GlkOtgCHFH8aidYth3aQHRHuClTi6Y9mYRJtqqK-FNQYq4ZP23DSGZGFejJFTnM9YMpppuTMLklhSGySwX8rfjZ_0L5ac18nHaykTaiC2fvH00W42qQ"   } } 

Controller

using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Programming.DotNetCore.Function.Entity.Jwt; using Programming.DotNetCore.Function.Interface.PasswordService; using Programming.DotNetCore.Function.Password.Entity;  namespace Cnpc.Com.Ioc.WebApp.Controllers {     [Route("api/[controller]/[Action]")]     [ApiController]     public class TestJwtController : ControllerBase     {         IPassWordService _passWordService;         JwtConfig _jwtconfig;          public TestJwtController(IPassWordService passWordService,IOptions<JwtConfig> jwtconfig)          {             _passWordService = passWordService;             _jwtconfig = jwtconfig.Value;         }          [HttpGet]         public IActionResult Login(string userName,string passWord)         {             string token = _passWordService.GetToken(new()             {                 UserName = userName,                 Extended1 = "无信息",                 Role = new List<RoleInfo>()                  {                      new RoleInfo() { Id = "1",Role="系统管理员"} ,                     new RoleInfo() { Id = "2",Role="用户管理员"} ,                 }             }, new()             {                 Audience = _jwtconfig.Audience,                 Issuer= _jwtconfig.Issuer,                 SecurityKey= _jwtconfig.SecurityKey,                 ExpiresMinutes = 5,             });              return new JsonResult(new { token = token });          }     } }  

.Net Core 验证(webApi)

Progarm

添加JWT验证

builder.Services.AddAuthentication(options => {     options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => {     options.TokenValidationParameters = new TokenValidationParameters()     {         ValidateIssuer = true,         ValidIssuer = jwtConfig.Issuer, //发行人         ValidateAudience = true,         ValidAudience = jwtConfig.Audience,//订阅人         ValidateIssuerSigningKey = true,         //对称加密密钥         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey!)),         ValidateLifetime = true, //验证失效时间         ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值         RequireExpirationTime = true,         AudienceValidator = (audiences, securityToken, validationParameters) =>         {             return true;         },         LifetimeValidator = (notBefore,expires,  securityToken, validationParameters) =>         {             return true;         }     }; }); 

读取配置文件

JwtConfig jwtConfig = new JwtConfig(); builder.Configuration.Bind("JwtTokenOptions", jwtConfig); 

添加Swagger支持,api右上角可以写Token

builder.Services.AddSwaggerGen(c => {     //添加Jwt验证设置,添加请求头信息     c.AddSecurityRequirement(new OpenApiSecurityRequirement     {         {             new OpenApiSecurityScheme             {                 Reference = new OpenApiReference                 {                     Id = "Bearer",                     Type = ReferenceType.SecurityScheme                 }             },             new List<string>()         }     });      //放置接口Auth授权按钮     c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme     {         Description = "Value Bearer {token}",         Name = "Authorization",//jwt默认的参数名称         In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)         Type = SecuritySchemeType.ApiKey     }); }); ; 

Contorller

using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Programming.DotNetCore.Function.Entity.Jwt; using Programming.DotNetCore.Function.Interface.PasswordService; using Programming.DotNetCore.Function.Password.Entity;  namespace Cnpc.Com.Ioc.WebApp.Controllers {     [Route("api/[controller]/[Action]")]     [ApiController]     public class TestJwtController : ControllerBase     {         [HttpGet]         [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]         public IActionResult TestApi()         {             //获取用户Claim信息             var user = HttpContext.User.Claims.Select(it => new { it.Type,it.Value});             return new JsonResult(user);         }     } } 

.Net Core 授权

简介

可以在数据库中进一步验证访问接口的权限

Program.cs

//jwt 授权 builder.Services.AddAuthorization(options => {     options.AddPolicy("JwtPolicy", policy =>     {         //jwt 授权         policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)         //这里为自定义授权指定一下类         .AddRequirements(new UserRoleRequirement(JwtBearerDefaults.AuthenticationScheme));      }); }); 

JwtAuthorization.cs

注意

验证中涉及到 IUserServices 和 JwtAuthorization, 需要在ioc容器中注册一下,我这里使用的是Autofac注册,如果使用系统自带的注册可以这么写:

  • builder.Services.AddTransient<IUserServices, IUserServices>();
  • builder.Services.AddTransient<IAuthorizationHandler, JwtAuthorization>();

Autofac 注册授权服务

using Autofac; using Autofac.Extras.DynamicProxy; using Castle.DynamicProxy; using Cnpc.Com.Ioc.Bll; using Cnpc.Com.Ioc.Dal; using Cnpc.Com.Ioc.IBll; using Cnpc.Com.Ioc.IDal; using Cnpc.Com.Ioc.Tools; using Cnpc.Com.Ioc.WebApp.Authorization; using Cnpc.Com.Ioc.WebApp.Filter.ActionFilter; using Microsoft.AspNetCore.Authorization; using Programming.DotNetCore.Function.Interface.PasswordService; using Programming.DotNetCore.Function.Password;  namespace WepApiTest.Autofac {     public class AutofacConfig : Module     {          protected override void Load(ContainerBuilder builder)         {             //ioc             builder.RegisterType<JwtAuthorization>().As<IAuthorizationHandler>();             builder.RegisterType<UserServices>().As<IUserServices>();         }     } } 
using Cnpc.Com.Ioc.IBll; using Microsoft.AspNetCore.Authorization; using System.Security.Claims;  namespace Cnpc.Com.Ioc.WebApp.Authorization {     public class UserRoleRequirement : IAuthorizationRequirement     {         public string AuthenticateScheme;         public UserRoleRequirement(string authenticateScheme)         {             AuthenticateScheme = authenticateScheme;         }     }     public class JwtAuthorization : AuthorizationHandler<UserRoleRequirement>     {         IUserServices userSercices;         public JwtAuthorization(IUserServices userSercices)         {             this.userSercices = userSercices;         }         protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserRoleRequirement requirement)         {             string? userName = context.User.FindFirst(it => it.Type == ClaimTypes.Name)?.Value;             if (userSercices.IsAdmin(userName!))             {                 context.Succeed(requirement);             }             else             {                 context.Fail();             }             return Task.CompletedTask;         }     } } 

Controller

注意

唯一需要修改的地方就是这里, 指定Policy 为 Program.cs 中设置授权方案名称

  • [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,Policy = "JwtPolicy")]

using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Programming.DotNetCore.Function.Entity.Jwt; using Programming.DotNetCore.Function.Interface.PasswordService; using Programming.DotNetCore.Function.Password.Entity;  namespace Cnpc.Com.Ioc.WebApp.Controllers {     [Route("api/[controller]/[Action]")]     [ApiController]     public class TestJwtController : ControllerBase     {         [HttpGet]         [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,Policy = "JwtPolicy")]         public IActionResult TestApi()         {             var user = HttpContext.User.Claims.Select(it => new { it.Type,it.Value});             return new JsonResult(user);         }     } }