首页 > 其他分享 >WebAPI项目框架JWT权限验证

WebAPI项目框架JWT权限验证

时间:2024-07-02 20:53:53浏览次数:23  
标签:WebAPI Claim string AppSettings JWT var new 权限 public

JWT是什么?校验逻辑?授权过程?这里就不过多的阐述了,直接上代码

在appsettings.json中配置jwt参数的值

SecretKey必须大于16个字符

 1 {
 2   "Logging": {
 3     "LogLevel": {
 4       "Default": "Information",
 5       "Microsoft.AspNetCore": "Warning"
 6     }
 7   },
 8   "AllowedHosts": "*",
 9   "AppSettings": {
10     //数据库连接字符串
11     "ConnectionString": "server=192.168.132.131;uid=sa;pwd=6014359wQ@!;database=MagCoreDB",
12     "JwtSetting": {
13       "Issuer": "jwtIssuer", //颁发者
14       "Audience": "jwtAudience", //可以给哪些客户端使用
15       "SecretKey": "yehjsiwkjhuhgyehsnd" //加密Key
16     }
17   }
18 }

Nuget安装以下三个包:

在web.core.model中新建类TokenModel:

 1 /// <summary>
 2     /// 令牌
 3     /// </summary>
 4     public class TokenModel
 5     {
 6         /// <summary>
 7         /// Id
 8         /// </summary>
 9         public string Uid { get; set; }
10         /// <summary>
11         /// 角色
12         /// </summary>
13         public string Role { get; set; }
14 
15     }

新建JwtHelper.cs帮助类 

 1 public class JwtHelper
 2     {
 3         /// <summary>
 4         /// 颁发JWT字符串
 5         /// </summary>
 6         /// <param name="tokenModel"></param>
 7         /// <returns></returns>
 8         public static string IssueJwt(TokenModel tokenModel)
 9         {
10             //获取Appsetting配置
11             string iss = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "Issuer" });
12             string aud = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "Audience" });
13             string secret = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "SecretKey" });
14 
15             //var claims = new Claim[] //old
16             var claims = new List<Claim>
17                 {
18                  /*
19                  * 特别重要:
20                    1、这里将用户的部分信息,比如 uid 存到了Claim 中,如果你想知道如何在其他地方将这个 uid从 Token 中取出来,请看下边的SerializeJwt() 方法,或者在整个解决方案,搜索这个方法,看哪里使用了!
21                    2、你也可以研究下 HttpContext.User.Claims ,具体的你可以看看 Policys/PermissionHandler.cs 类中是如何使用的。
22                  */
23                 new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()),
24                 new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
25                 new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
26                 //这个就是过期时间,目前是过期1000秒,可自定义,注意JWT有自己的缓冲过期时间
27                 new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds()}"),
28                 new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(1000).ToString()),
29                 new Claim(JwtRegisteredClaimNames.Iss,iss),
30                 new Claim(JwtRegisteredClaimNames.Aud,aud),
31 
32                };
33 
34             // 可以将一个用户的多个角色全部赋予;
35             claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
36 
37 
38 
39             //秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)
40             var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
41             var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
42 
43             var jwt = new JwtSecurityToken(
44                 issuer: iss,
45                 claims: claims,
46                 signingCredentials: creds);
47 
48             var jwtHandler = new JwtSecurityTokenHandler();
49             var encodedJwt = jwtHandler.WriteToken(jwt);
50 
51             return encodedJwt;
52         }
53 
54         /// <summary>
55         /// 解析
56         /// </summary>
57         /// <param name="jwtStr"></param>
58         /// <returns></returns>
59         public static TokenModel SerializeJwt(string jwtStr)
60         {
61             var jwtHandler = new JwtSecurityTokenHandler();
62             JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
63             object role;
64             try
65             {
66                 jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);
67             }
68             catch (Exception e)
69             {
70                 Console.WriteLine(e);
71                 throw;
72             }
73             var tm = new TokenModel
74             {
75                 Uid = jwtToken.Id.ToString(),
76                 Role = role != null ? role.ToString() : "",
77             };
78             return tm;
79         }
80     }

在HomeController中新建Login接口来获取Token

 1 /// <summary>
 2         /// 获取Token
 3         /// </summary>
 4         /// <param name="rolename"></param>
 5         /// <param name="password"></param>
 6         /// <returns></returns>
 7         [HttpGet]
 8         [AllowAnonymous]
 9         public async Task<IActionResult> Login(string rolename, string password)
10         {
11             string jwtStr = string.Empty;
12             bool suc = false;
13 
14             if (rolename != null && password != null)
15             {
16                 if (rolename != "Admin" && password != "123456")
17                 {
18                     jwtStr = "输入不正确!";
19                 }
20                 else
21                 {
22                     // 将用户id和角色名,作为单独的自定义变量封装进 token 字符串中。
23                     TokenModel tokenModel = new TokenModel { Uid = "1", Role = rolename };
24                     jwtStr = JwtHelper.IssueJwt(tokenModel);//登录,获取到一定规则的 Token 令牌
25                     suc = true;
26                 }
27             }
28             else
29             {
30                 jwtStr = "输入不能为空!";
31             }
32 
33             return Ok(new
34             {
35                 success = suc,
36                 token = jwtStr
37             });
38         }

运行项目,输入Admin,123456,获取Token:

JWT权限验证,就需要开启验证,然后输入token令牌,然后在SwaggerSetUp.cs的AddSwaggerSetup方法的AddSwaggerGen服务中,添加代码:

 1 services.AddSwaggerGen(c =>
 2             {
 3                 c.SwaggerDoc("V1", new OpenApiInfo
 4                 {
 5                     // {ApiName} 定义成全局变量,方便修改
 6                     Version = "V1",
 7                     Title = $"{ApiName} 接口文档——.NetCore 6.0",
 8                     Description = $"{ApiName} HTTP API V1",
 9                     //Contact = new OpenApiContact { Name = ApiName, Email = "[email protected]", Url = new Uri("https://www.jianshu.com/u/94102b59cc2a") },
10                     //License = new OpenApiLicense { Name = ApiName, Url = new Uri("https://www.jianshu.com/u/94102b59cc2a") }
11                 });
12                 c.OrderActionsBy(o => o.RelativePath);
13 
14                 var xmlPath = Path.Combine(AppContext.BaseDirectory, "Mag.Core.API.xml");//这个就是刚刚配置的xml文件名
15                 c.IncludeXmlComments(xmlPath, true);//默认的第二个参数是false,这个是controller的注释,记得修改
16                 var xmlModelPath = Path.Combine(AppContext.BaseDirectory, "Mag.Core.Model.xml");//这个就是Model层的xml文件名
17                 c.IncludeXmlComments(xmlModelPath);
18 
19                 // 在header中添加token,传递到后台
20                 c.OperationFilter<SecurityRequirementsOperationFilter>();
21 
22                 #region Token绑定到ConfigureServices
23                 c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
24                 {
25                     Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
26                     Name = "Authorization",//jwt默认的参数名称
27                     In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
28                     Type = SecuritySchemeType.ApiKey
29                 });
30                 #endregion
31             });

运行项目,就可以看见JWT验证入口:

在SetUp文件夹里面新建注册方法AuthorizationSetup.cs

 1 public static class AuthorizationSetup
 2     {
 3         public static void AddAuthorizationSetup(this IServiceCollection services)
 4         {
 5             if (services == null) throw new ArgumentNullException(nameof(services));
 6 
 7             // 1【授权】、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。
 8             // 然后这么写 [Authorize(Policy = "Admin")]
 9             services.AddAuthorization(options =>
10             {
11                 options.AddPolicy("User", policy => policy.RequireRole("User").Build());
12                 options.AddPolicy("System", policy => policy.RequireRole("System").Build());
13                 options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
14 
15             });
16 
17             //读取配置文件
18             var symmetricKeyAsBase64 = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "SecretKey" });
19             var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
20             var signingKey = new SymmetricSecurityKey(keyByteArray);
21             var Issuer = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "Issuer" });
22             var Audience = AppSettings.app(new string[] { "AppSettings", "JwtSetting", "Audience" });
23 
24 
25 
26             // 令牌验证参数
27             var tokenValidationParameters = new TokenValidationParameters
28             {
29                 ValidateIssuerSigningKey = true,
30                 IssuerSigningKey = signingKey,
31                 ValidateIssuer = true,
32                 ValidIssuer = Issuer,//发行人
33                 ValidateAudience = true,
34                 ValidAudience = Audience,//订阅人
35                 ValidateLifetime = true,
36                 ClockSkew = TimeSpan.FromSeconds(30),
37                 RequireExpirationTime = true,
38             };
39 
40             //2.1【认证】、core自带官方JWT认证
41             // 开启Bearer认证
42             services.AddAuthentication("Bearer")
43              // 添加JwtBearer服务
44              .AddJwtBearer(o =>
45              {
46                  o.TokenValidationParameters = tokenValidationParameters;
47                  o.Events = new JwtBearerEvents
48                  {
49                      OnAuthenticationFailed = context =>
50                      {
51                          // 如果过期,则把<是否过期>添加到,返回头信息中
52                          if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
53                          {
54                              context.Response.Headers.Add("Token-Expired", "true");
55                          }
56                          return Task.CompletedTask;
57                      }
58                  };
59              });
60 
61 
62 
63         }
64     }

在program.cs里面注册服务,开启服务

//jwt授权验证
builder.Services.AddAuthorizationSetup();
app.UseAuthentication();

在BaseApiController里面设置全局权限验证:

没有验证权限会提示401:

 

设置获取token的时候 [AllowAnonymous],无需验证:

 

设置测试方法:需要System的权限才能访问:

上面我们是用的Admin的权限,所以会提示403错误

 新增解析Token的方法:

 1 /// <summary>
 2         /// 解析Token
 3         /// </summary>
 4         /// <returns></returns>
 5         [HttpGet]
 6         [Authorize]
 7         public IActionResult ParseToken()
 8         {
 9             //需要截取Bearer 
10             var tokenHeader = HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
11             var user = JwtHelper.SerializeJwt(tokenHeader);
12             return Ok(user);
13 
14         }

解析出来的role是Admin。

 

标签:WebAPI,Claim,string,AppSettings,JWT,var,new,权限,public
From: https://www.cnblogs.com/leon1128/p/18280526

相关文章

  • WebAPI项目框架新建读取配置文件帮助类
    在.netcorewebapi项目中,我们会把配置信息同意放置在appsettings.json中,通过新建读取帮助类,更加简单的读取配置信息。新建公共类库文件夹Common,新建公共类库Web.Core.Common在Web.Core.Common类库下新建Helper文件夹,新建AppSettings帮助类 .NetCore6.0WebAPI项目框架搭......
  • Java实现登录验证 -- JWT令牌实现
    目录1.实现登录验证的引出原因2.JWT令牌2.1使用JWT令牌时2.2令牌的组成三.JWT令牌(token)生成和校验3.1引入JWT令牌的依赖3.2使用Jar包中提供的API来实现JWT令牌的生成和校验3.3使用JWT令牌验证登录1.实现登录验证的引出传统思路下:登录页面把用户名和密码交......
  • Spring Boot 中使用 Spring Security 实现安全访问权限管理:详尽指南
    引言:在现代Web应用开发中,安全是一个至关重要的环节。SpringSecurity是一个功能强大且高度可定制的安全框架,能够为SpringBoot应用提供全面的安全解决方案,包括认证(Authentication)和授权(Authorization)。本文将手把手教你如何在SpringBoot应用中集成SpringSecurity,实现用户登......
  • 搭建sftp并且保证普通用户有权限操作对应文件
    创建SFTP用户组为SFTP用户创建一个专用组:groupaddsftpusers创建SFTP用户创建SFTP用户splsz并将其添加到sftpusers组,同时指定用户的主目录和禁止shell访问:useradd-gsftpusers-s/sbin/nologinsplszpasswdsplsz创建目录结构sudomkdir-p/home/zhangqiang/davinci/......
  • springboot项目登陆校验————基于Jwt令牌和Fliter / Interceptor
    springboot项目登陆校验————基于Jwt令牌和Fliter/Interceptor文章目录springboot项目登陆校验————基于Jwt令牌和Fliter/Interceptor1.概述2.Jwt令牌2.1Jwt令牌的组成2.2Jwt登录认证流程2.3代码实现3.方法1:Fliter过滤器3.1简介3.1代码实现4.方法2:Interce......
  • 338 Authorization with JWT
    步骤1、客户端添加headerscities.service.tsimport{Injectable}from'@angular/core';import{City}from"../models/city";import{HttpClient,HttpHeaders}from"@angular/common/http";import{Observable}from"rxjs"......
  • 【Linux】解锁权限的神秘面纱,让你的系统更安全、更高效!
    XShell原理+权限1.Shell命令以及运行原理*1.1Shell外壳1.2shell周边知识2.Linux权限的概念*2.1用户2.2用户切换2.3sudo3.Linux权限管理*3.1文件访问者的分类3.2文件类型3.3file指令3.4文件访问权限3.5文件权限值的表示方法4.文件访问权限的设......
  • WebApi读取配置文件帮助类
    1///<summary>2///appsettings.json操作类3///</summary>4publicclassAppSettings5{6staticIConfigurationConfiguration{get;set;}7staticstringcontentPath{get;set;}89p......
  • 在Linux中,如何使用xargs和exec实现把当前目录下所有后缀名为.txt的⽂件的权限修改为77
    在Linux中,要使用xargs和exec结合find命令来批量修改当前目录下所有后缀名为.txt的文件权限为777,可以按照以下步骤操作:查找.txt文件:首先,使用find命令来查找当前目录及其子目录下的所有.txt文件。这里我们使用-name"*.txt"来指定查找的文件名模式。传递给xargs:然后,通过管......
  • webAPI连接SQLserver,并快速建立数据模型
    首先,你需要有一个webAPI来作为Android应用和SQLserver数据库之间的中间件,创建该api在项目中导入三个NuGet包通过服务器资源管理器连接数据库,获取数据库连接的字符串 快速建立数据模型思路:通过数据库创建数据类:导入包=>打开程序包管理器控制台=>选择项目=>Scaffold-DbCont......