C# EAI JWT Token 验证流程分析
这里请求端,服务端,Token的生成、获取、验证,请求发送都是在本地本项目中完成。因为后面大约会做到EAI同步数据,就想现在本地电脑上先试试。
·
因为后面大约会做到EAI同步数据,就想现在本地电脑上先试试。
这里请求端,服务端,Token的生成、获取、验证,请求发送都是在本地本项目中完成。
- 作为服务端Token生成,在启动类中配置一个请求,用于用户生成并获取Token。这里就是获取请求时携带的用户名,配合配置文件里面的密钥等信息,生成的一个Token。再配置一个有效期。
// 生成Token的端点 app.MapPost("/AA/GetToken", (LoginRequest request) => { // 实际项目应在此处验证用户名密码 var claims = new[] { new Claim(ClaimTypes.Name, request.Email), new Claim(JwtRegisteredClaimNames.Sub, request.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var key = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: builder.Configuration["Jwt:Issuer"],//(签发者)用于标识Token的发行方,一般是基础网址 audience: builder.Configuration["Jwt:Audience"],//受众,与Issuer构成双重验证 claims: claims,//身份认证的数据 expires: DateTime.Now.AddMinutes(30),//token 有效期 signingCredentials: creds);//创建对称加密密钥,绑定加密算法 return Results.Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) }); }); app.UseAuthentication(); app.UseAuthorization();
- 以上里面用到的配置文件项,在appsettings.json中。
{ "Jwt": { "Key": "YourSuperSecretKeyWith32Characters", "Issuer": "https://localhost:7093", "Audience": "MES" }, "ConnectionStrings": { "HangfireConnection": "server=localhost;user=root;password=admin;database=test;Allow User Variables=True" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
- 然后在Program.cs配置下Swagger,因为每次请求都手动配置Token到请求头里面会比较麻烦,所以这里配置后,每个请求就会自动携带Token。
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new() { Title = "JWT Auth API", Version = "v1" }); // JWT Bearer认证配置 c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization头使用Bearer scheme. 格式: \"Bearer token\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, Array.Empty<string>() } }); });
- 看下效果
这里配置Token
这里获取Token,注意配置Token的格式,有空格,没有{},eg:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiamlhbmciLCJzdWIiOiJqaWFuZyIsImp0aSI6IjMxNWQwOWY0LTE2ODAtNGQwOC04M2ZhLTcwMzhmM2MyZjY4OSIsImV4cCI6MTc1NzM4OTcxMywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NzA5MyIsImF1ZCI6Ik1FUyJ9.GSK1Qd8v0Rxbep5EU3gSkeLxxrG8yYHTNhLA3NNwvxM
- 调试模式能看到Header里面的Authorization里面的配置Token
- 还有Controller里面要写Authorize注解,不然不生效
- 然后就是验证Token,这里有自动验证的配置,还写了一个主动验证的,好像没用上
// 配置JWT认证 JWT配置注入 验证token用 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ClockSkew = TimeSpan.Zero, // 消除时钟偏移 ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; });
- 这里是Controller转别的请求,预计后面请求EAI的开放接口就可从这里发起,具体的参数传递,数据接收解析存储,后面再说吧。
//https://localhost:7093/AA [HttpPost(Name = "Index")] public async Task<ActionResult> IndexAsync() { try { /* User user = new User(); user.UserNo = "1"; user.UserID = "001"; user.Name = "AA";*/ _httpClient = _factory.CreateClient("MyClient"); //手动获取请求里面的token,放入新的请求头里面 var token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(' ').Last(); var tokenClient = new TokenHttpClient(_httpClient, token); var response = await tokenClient.SendRequestWithTokenAsync( "https://localhost:7093/AA/GetDetail", HttpMethod.Post); //var response = await JsonSender.PostJsonAsync(token, // "AA/GetDetail", // user); Console.WriteLine($"响应内容: {response}"); return Ok(response); //return new ApiResponse<object> { Success = true, Data = response }; } catch (Exception ex) { return new ApiResponse<object> { Success = false, Message = ex.Message }; } }
-
效果,附测试代码
更多推荐
所有评论(0)