ASP.NET Core Ocelot+Consul+Nginx+JWT 构建微服务鉴权中心
2022/4/17 7:13:06
本文主要是介绍ASP.NET Core Ocelot+Consul+Nginx+JWT 构建微服务鉴权中心,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- ASP.NET Core Ocelot+Consul+Nginx+JWT 构建微服务鉴权中心
- 鉴权中心 Common.AuthenticationCenter
- Controllers文件
- AuthenticationController.cs
- Utility 文件夹
- Model 文件夹
- User.cs
- RSA 文件夹
- RSAHelper.cs
- Model 文件夹
- ConfigInformation.cs
- HttpHelperService.cs
- IJWTService.cs
- JWTHSService.cs
- JWTRSService.cs
- JWTTokenOptions.cs
- appsettings.json
- key.json
- Program.cs
- Controllers文件
- 网关 Common.OcelotGateway
- appsettings.json
- OcelotConfiguration.json
- Program.cs
- 用户微服务 UserMicroservice
- Controllers文件夹
- UserController.cs
- appsettings.json
- Program.cs
- Controllers文件夹
- 课程微服务 LessonMicroservice
- Controllers文件夹
- LessonController.cs
- appsettings.json
- Program.cs
- Controllers文件夹
ASP.NET Core Ocelot+Consul+Nginx+JWT 构建微服务鉴权中心
- 构建鉴权中心 通过webapi的形式给微服务颁发可以登录的有效JWT Token
- 构建用户微服务 管理用户信息
- 构建测试用微服务
- 构建网关层,对微服务进行转发和鉴权
- 使用Consul 进行服务的注册 发现
访问流程:
Nginx=>3个鉴权中心集群=》访问问User 微服务验证用户正确性=》验证成功鉴权中心颁发有效Token
Nginx=>(网管层)Ocelot 鉴权=》Consul(服务注册发现)=》测试微服务
鉴权中心 Common.AuthenticationCenter
Controllers文件
AuthenticationController.cs
通过访问用户微服务的登录接口,如果登录成功就颁发JWT Token
[Route("api/[controller]")] [ApiController] public class AuthenticationController : ControllerBase { #region MyRegion private ILogger<AuthenticationController> _logger = null; private IJWTService _iJWTService = null; private readonly IConfiguration _iConfiguration; private HttpHelperService _HttpHelperService = null; public AuthenticationController(ILoggerFactory factory, ILogger<AuthenticationController> logger, IConfiguration configuration , IJWTService service , HttpHelperService httpHelperService) { this._logger = logger; this._iConfiguration = configuration; this._iJWTService = service; _HttpHelperService = httpHelperService; } #endregion MyRegion [Route("Get")] [HttpGet] public IEnumerable<int> Get() { return new List<int>() { 1, 2, 3, 4, 6, 7 }; } [Route("GetKey")] [HttpGet] public string GetKey() { string keyDir = Directory.GetCurrentDirectory(); if (RSAHelper.TryGetKeyParameters(keyDir, false, out RSAParameters keyParams) == false) { keyParams = RSAHelper.GenerateAndSaveKey(keyDir, false); } return JsonConvert.SerializeObject(keyParams); //return ""; } [Route("Login")] [HttpPost] public HttpJsonResponse Login([FromForm] string username, [FromForm] string password) { User user = _HttpHelperService.VerifyUser(username, password); if (user is not null)//应该数据库 { string token = this._iJWTService.GetToken(username, password, user); return HttpJsonResponse.SuccessResult(token); } else { return HttpJsonResponse.FailedResult("校验失败"); } } }
Utility 文件夹
Model 文件夹
User.cs
用户微服务的 Model 抽象
public class User { /// <summary> /// 主键ID /// </summary> public long Id { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateTime { get; set; } = DateTime.Now; /// <summary> /// 修改时间 /// </summary> public DateTime UpdateTime { get; set; } = DateTime.Now; /// <summary> /// 用户名 /// </summary> public string UserName { get; set; } = string.Empty; /// <summary> /// 密码 /// </summary> public string Password { get; set; } = string.Empty; /// <summary> /// 用户昵称 /// </summary> public string NickName { get; set; } = string.Empty; /// <summary> /// 用户部门ID /// </summary> public long DepartmentId { get; set; } = -1; /// <summary> /// 用户头像 /// </summary> public string Avatar { get; set; } = string.Empty; /// <summary> /// 是否是老师 /// </summary> public bool IsTeacher { get; set; } = false; /// <summary> /// 用户规则ID 测试期间 方便测试暂不关联规则表 -1表示普通用户具有查询权限 0代表管理员具有增加 删除 修改权限 /// </summary> public long RoleId { get; set; } = -1; }
RSA 文件夹
RSAHelper.cs
public class RSAHelper { /// <summary> /// 从本地文件中读取用来签发 Token 的 RSA Key /// </summary> /// <param name="filePath">存放密钥的文件夹路径</param> /// <param name="withPrivate"></param> /// <param name="keyParameters"></param> /// <returns></returns> public static bool TryGetKeyParameters(string filePath, bool withPrivate, out RSAParameters keyParameters) { string filename = withPrivate ? "key.json" : "key.public.json"; string fileTotalPath = Path.Combine(filePath, filename); keyParameters = default(RSAParameters); if (!File.Exists(fileTotalPath)) { return false; } else { keyParameters = JsonConvert.DeserializeObject<RSAParameters>(File.ReadAllText(fileTotalPath)); return true; } } /// <summary> /// 生成并保存 RSA 公钥与私钥 /// </summary> /// <param name="filePath">存放密钥的文件夹路径</param> /// <returns></returns> public static RSAParameters GenerateAndSaveKey(string filePath, bool withPrivate = true) { RSAParameters publicKeys, privateKeys; using (var rsa = new RSACryptoServiceProvider(2048))//即时生成 { try { privateKeys = rsa.ExportParameters(true); publicKeys = rsa.ExportParameters(false); } finally { rsa.PersistKeyInCsp = false; } } File.WriteAllText(Path.Combine(filePath, "key.json"), JsonConvert.SerializeObject(privateKeys)); File.WriteAllText(Path.Combine(filePath, "key.public.json"), JsonConvert.SerializeObject(publicKeys)); return withPrivate ? privateKeys : publicKeys; } //public static string GenerateAndSaveKey(string filePath, bool withPrivate = true) //{ // //RSAParameters publicKeys, privateKeys; // using (var rsa = new RSACryptoServiceProvider(2048))//即时生成 // { // try // { // //privateKeys = rsa.ExportParameters(true); // //publicKeys = rsa.ExportParameters(false); // //rsa.ExportRSAPublicKey(); // //rsa.ExportRSAPrivateKey(); // string publicKey = rsa.ToXmlString(false);//publickey // string privateKey = rsa.ToXmlString(true);//privateKey // File.WriteAllText(Path.Combine(filePath, "key.json"), privateKey); // File.WriteAllText(Path.Combine(filePath, "key.public.json"), publicKey); // return withPrivate ? privateKey : publicKey; // } // finally // { // rsa.PersistKeyInCsp = false; // } // } //} }
ConfigInformation.cs
public class ConfigInformation { public string RootUrl { get; set; } public string UserUrl { get; set; } public JWTTokenOptions JWTTokenOptions { get; set; } }
HttpHelperService.cs
/// <summary> /// 就是去调用服务的---暂时没有Consul---ToDo /// </summary> public class HttpHelperService { #region Option注入 private readonly ConfigInformation _ConfigInformation; public HttpHelperService(IOptionsMonitor<ConfigInformation> configInformation) { this._ConfigInformation = configInformation.CurrentValue; } #endregion Option注入 public User VerifyUser(string name, string password) { string requestUrl = $"{_ConfigInformation.RootUrl}{_ConfigInformation.UserUrl}?username={name}&password={password}"; Console.WriteLine(requestUrl); HttpResponseMessage sResult = this.HttpRequest(requestUrl, HttpMethod.Get, null); if (sResult.IsSuccessStatusCode) { string content = sResult.Content.ReadAsStringAsync().Result; HttpJsonResponse response = JsonConvert.DeserializeObject<HttpJsonResponse>(content); User user = JsonConvert.DeserializeObject<User>(JsonConvert.SerializeObject(response.Data)); return user; } else { return null; } } public HttpResponseMessage HttpRequest(string url, HttpMethod httpMethod, Dictionary<string, string> parameter) { using (HttpClient httpClient = new HttpClient()) { HttpRequestMessage message = new HttpRequestMessage() { Method = httpMethod, RequestUri = new Uri(url) }; if (parameter != null) { var encodedContent = new FormUrlEncodedContent(parameter); message.Content = encodedContent; } return httpClient.SendAsync(message).Result; } } }
IJWTService.cs
/// <summary> /// 封装注入 /// </summary> public interface IJWTService { /// <summary> /// 获取Token /// </summary> /// <param name="UserName">账号</param> /// <param name="password">密码</param> /// <param name="user">用户信息</param> /// <returns></returns> string GetToken(string UserName, string password, User user); }
JWTHSService.cs
public class JWTHSService : IJWTService { #region Option注入 private readonly JWTTokenOptions _JWTTokenOptions; public JWTHSService(IOptionsMonitor<ConfigInformation> configInformation) { this._JWTTokenOptions = configInformation.CurrentValue.JWTTokenOptions; } #endregion Option注入 public string GetToken(string UserName, string password, User user) { var claims = new[] { new Claim("username", user.UserName), new Claim("id", user.Id.ToString()), new Claim(ClaimTypes.Role,user.RoleId.ToString()) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._JWTTokenOptions.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: this._JWTTokenOptions.Issuer, audience: this._JWTTokenOptions.Audience, claims: claims, expires: DateTime.Now.AddMinutes(60),//5分钟有效期 notBefore: DateTime.Now.AddMilliseconds(5),//1分钟后有效 signingCredentials: creds); string returnToken = new JwtSecurityTokenHandler().WriteToken(token); return returnToken; } }
JWTRSService.cs
public class JWTRSService : IJWTService { #region Option注入 private readonly JWTTokenOptions _JWTTokenOptions; public JWTRSService(IOptionsMonitor<ConfigInformation> configInformation) { this._JWTTokenOptions = configInformation.CurrentValue.JWTTokenOptions; } #endregion Option注入 public string GetToken(string userName, string password, User user) { string jtiCustom = Guid.NewGuid().ToString();//用来标识 Token var claims = new[] { new Claim(ClaimTypes.Name, user.UserName), new Claim("id", user.Id.ToString()), new Claim(ClaimTypes.Role,user.RoleId.ToString()) }; string keyDir = Directory.GetCurrentDirectory(); if (RSAHelper.TryGetKeyParameters(keyDir, true, out RSAParameters keyParams) == false) { keyParams = RSAHelper.GenerateAndSaveKey(keyDir); } var credentials = new SigningCredentials(new RsaSecurityKey(keyParams), SecurityAlgorithms.RsaSha256Signature); #region XML //string privateKey = RSAHelper.GenerateAndSaveKey(keyDir); //var RSA = new RSACryptoServiceProvider(); //RSA.FromXmlString(privateKey); //var credentials = new SigningCredentials(new RsaSecurityKey(RSA), SecurityAlgorithms.RsaSha256Signature); #endregion XML var token = new JwtSecurityToken( issuer: this._JWTTokenOptions.Issuer, audience: this._JWTTokenOptions.Audience, claims: claims, expires: DateTime.Now.AddMinutes(60),//5分钟有效期 signingCredentials: credentials); var handler = new JwtSecurityTokenHandler(); string tokenString = handler.WriteToken(token); return tokenString; } }
JWTTokenOptions.cs
public class JWTTokenOptions { public string Audience { get; set; } public string SecurityKey { get; set; } //public SigningCredentials Credentials //{ // get; // set; //} public string Issuer { get; set; } }
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ConfigInformation": { "RootUrl": "http://localhost:10091", //服务调用 "UserUrl": "/api/userapi/User/validate", "JWTTokenOptions": { "Audience": "http://localhost:8761", "Issuer": "http://localhost:8761", "SecurityKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB" } } }
key.json
{"D":"ayJEcDAFTdAjKtn/wUvAe0z0RtXcOFENJm55PaTbDV8QAKfKKENY5K+nvU36uSi3qh2xP6NVoo3H3rDlk6X8AEuAOQs+arGfHQ/aL4Ob3skuEioHWszXScJ2KTzrrsolOik9SybNLRSMIgQKyZY5URk3BhLqSvMDwBQ2Nht/mlx+eQi1GpPgiJFH77BlRt3O/LKafAtgS292RxeKUJn3Q4dsn1PtJX+PMPT+bn+9PZXpQtSI8r8yUtrFja61WcGN8aJrG47EfT5wa3J/mcfhEK+4hU2uI3ycW+TaNjuxDZ+nAD4k3pcNT6a1ldSi3CnZKR2p/MUh07oazmx2QEg54Q==","DP":"t58aASvJT2+mQCi9EN5RksOXrgzGNB2U6PeS8NJ9ht6HiA78+fZKrfbxXxz8i/069Tyg7dkzYeKFd93q9FhFKqsOGE67gqjelKIXFTN2s2DFiJ7neFHkIhPisdS/a+SzHziFsxYHJbWobuHlrDw2QcoYGDsgS1Crbatn7t90Hfs=","DQ":"dzpHSw7DD1vwy+mOX5nRJLVniSmcIX8MMWtCXlmzj6CdUddyiGSGFhTB+hjVHLPxsJAzoV4zBFRt1s+CHGlgjhfD6ct58i7bDVG/6OVUI4v95iYiA7kPB44DlOzVjuhlGmTm5Tw5eTwjA3s/5FUuif0DShzt4jam7f+jlTvkXaM=","Exponent":"AQAB","InverseQ":"MTykln8IgIQ2DwhC4d0d/RXNk5/PvKXSY8goldKfxCiAwTmArivvuxfHC01oKFlZkZbPRVvh0rM9QkM4pX9ITfKd4+VoxmDtMMx5oEkbxKMbJQkUvJeADmtcy/zfXq8ZNSNcIkAI4setydA6tOvRZKuudJ5tEpXOxwTel8U5ltM=","Modulus":"o0jSDb5OYfSTPFPjZS67yovVQLEA5OIrey/1mBCH8Xxvo1zLwKPYzWwkRjzSLURZ19V9AeKAiP+JxDtGRzmUflqXY3e7vKeEosk5MoUj4MlBvxVxDL3bdghJaqhARaqsuXQ1dvOGABsDIogBmvCJyJOBHXISLl+hDGIOQSpHqtMFz4UHAF5v62x82oMYT8O4lTfoTSF1+jMH31rCCERXFEz2DUngdsT8gwQncTMrVTS2dIdacvkWmN0yvzLmMqZetv12p10O7jjuN61hlhhccAibGeU3X1veOHS4L9TzQ0rLPK/yTm3QlShWZD8oiLBnNXGhS0m/RTk3Uc7IrvvaqQ==","P":"0daJpBirbZIUYZyqeXW6csoy2eKDO81G4DAe0gzyZUk7ZQ97H3sIRdKU05lmeR0KuEtp71LOaljx2MJ1vawF4zoJ3MQEjzQYQS0Gq5zLPrX/Q+Sy/7Brb9oYlfwDzlyszlZqjSyJjupNOAlpkTkytt6a5g6LtD44mo2A9XCteTM=","Q":"xzSFkOTiJGyTNatXO8pAxZyGg4qjAweJOL5wv5dGqFF7fWx92uJrMcGy6kda5A3aCE0KG0441fWjGPjzb6GvoTzwADRx4mNhOcVV0gx/lbKydc15KaBNEX29TkmYbG4dRQ5wOs+FBm0PAHcQgK64AFYhobG4w8VZBLxCXdwndLM="}
Program.cs
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<ConfigInformation>(builder.Configuration.GetSection("ConfigInformation")); builder.Services.AddTransient<HttpHelperService>(); builder.Services.AddControllers(); #region HS256 builder.Services.AddScoped<IJWTService, JWTHSService>(); //builder.Services.Configure<JWTTokenOptions>(builder.Configuration.GetSection("JWTTokenOptions")); #endregion HS256 #region RS256 //builder.Services.AddScoped<IJWTService, JWTRSService>(); //builder.Services.Configure<JWTTokenOptions>(builder.Configuration.GetSection("JWTTokenOptions")); #endregion RS256 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddCors(options => { options.AddPolicy("default", policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseSwagger(); app.UseSwaggerUI(); app.UseAuthorization(); app.UseCors("default"); app.MapControllers(); app.Run();
网关 Common.OcelotGateway
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "JWTTokenOptions": { "Audience": "http://localhost:8761", "Issuer": "http://localhost:8761", "SecurityKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB" } }
OcelotConfiguration.json
{ "Routes": [ { "UpstreamPathTemplate": "/api/lessonapi/{url}", "UpstreamHttpMethod": [ "Get", "Post", "Put", "Patch", "Delete", "Options" ], "UserServiceDIscovery": true, "ServiceName": "LessonCenter", "LoadBalancerOptions": { "Type": "RoundRobin" }, "DownstreamPathTemplate": "/api/lessonapi/{url}", "DownstreamScheme": "http", "DownstreamHeaderTransform": { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*" }, "AuthenticationOptions": { "AuthenticationProviderKey": "UserGatewayKey", "AllowedScopes": [] } }, { "UpstreamPathTemplate": "/lesson/swagger/v1/swagger.json", "UpstreamHttpMethod": [ "Get" ], "UseServiceDiscovery": true, "ServiceName": "LessonCenter", "LoadBalancerOptions": { "Type": "RoundRobin" }, "DownstreamPathTemplate": "/swagger/v1/swagger.json", "DownstreamScheme": "http", "RateLimitOptions": { "ClientWhiteList": [ "ajun816", "superhero" ], "EnableRateLimiting": true, "Period": "5m", "PeriodTimespan": 30, "Limit": 5 } }, { "UpstreamPathTemplate": "/api/userapi/{url}", "UpstreamHttpMethod": [ "Get", "Post", "Put", "Patch", "Delete", "Options" ], "UserServiceDIscovery": true, "ServiceName": "UserCenter", "LoadBalancerOptions": { "Type": "RoundRobin" }, "DownstreamPathTemplate": "/api/userapi/{url}", "DownstreamScheme": "http", "DownstreamHeaderTransform": { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*" } }, { "UpstreamPathTemplate": "/user/swagger/v1/swagger.json", "UpstreamHttpMethod": [ "Get" ], "UseServiceDiscovery": true, "ServiceName": "UserCenter", "LoadBalancerOptions": { "Type": "RoundRobin" }, "DownstreamPathTemplate": "/swagger/v1/swagger.json", "DownstreamScheme": "http", "RateLimitOptions": { "ClientWhiteList": [ "ajun816", "superhero" ], "EnableRateLimiting": true, "Period": "5m", "PeriodTimespan": 30, "Limit": 5 } }, "GlobalConfiguration": { "BaseUrl": "http://127.0.0.1:8070", //网关对外地址 "ServiceDiscoveryProvider": { "Host": "127.0.0.1", "Port": 8500, "Type": "Consul" //由Consul提供服务发现 }, "RateLimitOptions": { "QuotaExceededMessage": "Too many requests, maybe later? 11", // 当请求过载被截断时返回的消息 "HttpStatusCode": 666, // 当请求过载被截断时返回的http status "ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId } } }
Program.cs
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Common.OcelotGateway", Version = "v1" }); }); builder.Host.ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("OcelotConfiguration.json", optional: true, reloadOnChange: true); }); #region JWT检验 HS JWTTokenOptions tokenOptions = new JWTTokenOptions(); builder.Configuration.Bind("JWTTokenOptions", tokenOptions); string authenticationProviderKey = "UserGatewayKey"; builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//Bearer Scheme .AddJwtBearer(authenticationProviderKey, options => { options.TokenValidationParameters = new TokenValidationParameters { //JWT有一些默认的属性,就是给鉴权时就可以筛选了 ValidateIssuer = true,//是否验证Issuer ValidateAudience = true,//是否验证Audience ValidateLifetime = true,//是否验证失效时间---默认还添加了300s后才过期 ClockSkew = TimeSpan.FromSeconds(0),//token过期后立马过期 ValidateIssuerSigningKey = true,//是否验证SecurityKey ValidAudience = tokenOptions.Audience,//Audience,需要跟前面签发jwt的设置一致 ValidIssuer = tokenOptions.Issuer,//Issuer,这两项和前面签发jwt的设置一致 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.SecurityKey)),//拿到SecurityKey }; }); #endregion JWT检验 HS builder.Services.AddOcelot() .AddConsul() .AddPolly(); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/lesson/swagger/v1/swagger.json", "课程 API V1"); c.SwaggerEndpoint("/user/swagger/v1/swagger.json", "用户 API V1"); }); app.UseOcelot().Wait(); app.Run();
用户微服务 UserMicroservice
Controllers文件夹
UserController.cs
[Route("api/userapi/[controller]")] [ApiController] public class UserController : ControllerBase { private readonly IUserService? _userService; public UserController(IUserService? userService) { _userService = userService; } [HttpGet("all")] public HttpJsonResponse GetAll() { try { var data = _userService?.GetAll<SysUser>(); return HttpJsonResponse.SuccessResult(data); } catch { return HttpJsonResponse.FailedResult(); } } [Route("validate")] [HttpGet] public HttpJsonResponse ValidateUser(string username, string password) { try { var accountInfo = _userService?.ValidateUser(username, password); return HttpJsonResponse.SuccessResult(accountInfo); } catch (Exception ex) { return HttpJsonResponse.FailedResult(ex.Message); } } [HttpPost("regist")] public HttpJsonResponse CreateUser(RegisterModel registerModel) { try { var accountInfo = _userService?.CreateUser(registerModel); return HttpJsonResponse.SuccessResult(accountInfo); } catch (Exception ex) { return HttpJsonResponse.FailedResult(ex.Message); } } [HttpPut("update")] public HttpJsonResponse UpdateUser(RegisterModel registerModel) { try { var accountInfo = _userService?.UpdateUser(registerModel); return HttpJsonResponse.SuccessResult(accountInfo); } catch (Exception ex) { return HttpJsonResponse.FailedResult(ex.Message); } } [HttpDelete("delete/{id}")] public HttpJsonResponse DeleteUser([FromRoute] long id) { bool success = _userService?.Delete<SysUser>(id) ?? false; return success ? HttpJsonResponse.SuccessResult("删除成功") : HttpJsonResponse.FailedResult("删除失败"); } }
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "MySqlConn": "Server=111.44.222.111;Database=db_user;Uid=root;Pwd=111111;SslMode=none;" }, "CodeFirstSettings": { "Migrate": "true", //是否开启同步(是否进行codefirst创建表) "Backup": "true", //是否进行备份 "ModelPath": "UserModel" //要进行同步的Model程序集路径 }, "SqlSugarSnowFlakeSettings": { "WorkerId": "1" }, "ConsulClientOption": { "IP": "111.44.222.111", "Port": "18500", "Datacenter": "dc1" }, "ConsulRegisterOption": { "IP": "111.44.222.111", "Port": "8761", "GroupName": "UserCenter", "HealthCheckUrl": "http://111.44.222.111:8761/Health", "Interval": 10, "Timeout": 5, "DergisterCriticalServiceAfter": 20, "Tag": "13" } }
Program.cs
var builder = WebApplication.CreateBuilder(args); // 配置牛顿库,让json解析的时候使用我们自定义的解析器 这个解析器不会造成long类型数据的精度损失 builder.Services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.DateFormatString = "yyyy'-'MM'-'dd' 'HH':'mm':'ss"; options.SerializerSettings.ContractResolver = new CustomerJsonResolver(); }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // SqlSugar配置 builder.Services.AddSqlSugarSetup(builder.Configuration); // SqlSugar的雪花ID配置 builder.Services.AddSqlSugarSonwFlakeSetup(builder.Configuration); // SqlSugarCodeFirst设置 builder.Services.AddCodeFirstSetup(builder.Configuration, typeof(BaseModel)); builder.Services.AddTransient<IUserService, UserService>(); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "UserMicroservice V1")); app.UseAuthorization(); app.UsePerOptionsRequest(); app.UseHealthCheckMiddleware(); app.MapControllers(); app.UseConsulConfiguration(builder.Configuration).Wait(); app.Run();
课程微服务 LessonMicroservice
Controllers文件夹
LessonController.cs
[Route("api/lessonapi/[controller]")] [ApiController] public class LessonController : ControllerBase { #region 服务注入 private readonly ILessonService? _lessonService; public LessonController(ILessonService? lessonService) { _lessonService = lessonService; } #endregion 服务注入 /// <summary> /// 分页获取数据 /// </summary> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <returns></returns> [HttpGet("page")] public HttpJsonResponse GetPaged(int pageIndex = 1, int pageSize = 10) { var data = _lessonService?.GetLessons(pageIndex, pageSize, l => l.CreateTime); return HttpJsonResponse.SuccessResult(data); } /// <summary> /// 创建课程 /// </summary> /// <param name="lesson"></param> /// <returns></returns> [HttpPost("create")] [Authorize(Roles = "0")] public HttpJsonResponse Create(Lesson lesson) { var data = _lessonService?.CreateLesson(lesson); return HttpJsonResponse.SuccessResult(data); } /// <summary> /// 按条件筛选数据 /// </summary> /// <param name="filter"></param> /// <returns></returns> [HttpPost("filter")] public HttpJsonResponse GetPagedByFilter([FromBody] LessonFilter filter) { var data = _lessonService?.PagedLessonsByFilter(filter.GetFilterExpression(), filter.CategoryId, filter.PageIndex, filter.PageSize); return HttpJsonResponse.SuccessResult(data); } /// <summary> /// 按照Id删除数据 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpDelete("delete/{id}")] [Authorize(Roles = "0")] public HttpJsonResponse DeleteById([FromRoute] long id) { bool success = _lessonService?.DeleteLessonById(id) ?? false; return success ? HttpJsonResponse.SuccessResult(success) : HttpJsonResponse.FailedResult("删除课程失败!"); } /// <summary> /// 更新数据 /// </summary> /// <param name="lesson"></param> /// <returns></returns> [HttpPut("update")] [Authorize(Roles = "0")] public HttpJsonResponse Update(Lesson lesson) { var data = _lessonService?.Update<Lesson>(lesson); return HttpJsonResponse.SuccessResult(data); } }
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "MySqlConn": "Server=111.44.222.111;Database=db_Lesson;Uid=root;Pwd=111111;SslMode=none;" }, "CodeFirstSettings": { "Migrate": "true", //是否开启同步(是否进行codefirst创建表) "Backup": "true", //是否进行备份 "ModelPath": "LessonModel" //要进行同步的Model程序集路径 }, "SqlSugarSnowFlakeSettings": { "WorkerId": "1" }, "JWTTokenOptions": { "Audience": "http://localhost:8761", "Issuer": "http://localhost:8761", "SecurityKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB" }, //"ConsulClientOption": { // "IP": "111.44.222.111", // "Port": "18500", // "Datacenter": "dc1" //}, //"ConsulRegisterOption": { // "IP": "111.44.222.111", // "Port": "8761", // "GroupName": "LessonCenter", // "HealthCheckUrl": "http://111.44.222.111:8761/Health", // "Interval": 10, // "Timeout": 5, // "DergisterCriticalServiceAfter": 20, // "Tag": "13" //}, //本地测试ConsulClientOption "ConsulClientOption": { "IP": "localhost", "Port": "8500", "Datacenter": "dc1" }, "ConsulRegisterOption": { "IP": "localhost", "Port": "8761", "GroupName": "LessonCenter", "HealthCheckUrl": "http://localhost:8761/Health", "Interval": 10, "Timeout": 5, "DergisterCriticalServiceAfter": 20, "Tag": "13" } }
Program.cs
var builder = WebApplication.CreateBuilder(args); // Add services to the container. // 配置牛顿库,让json解析的时候使用我们自定义的解析器 这个解析器不会造成long类型数据的精度损失 builder.Services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.DateFormatString = "yyyy'-'MM'-'dd' 'HH':'mm':'ss"; options.SerializerSettings.ContractResolver = new CustomerJsonResolver(); }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // SqlSugar设置 builder.Services.AddSqlSugarSetup(builder.Configuration); // SqlSugar CodeFirst设置 builder.Services.AddCodeFirstSetup(builder.Configuration, typeof(BaseModel)); // SqlSugar 雪花ID设置 builder.Services.AddSqlSugarSonwFlakeSetup(builder.Configuration); // 服务注入 builder.Services.AddTransient<ILessonService, LessonService>(); #region jwt校验 HS JWTTokenOptions tokenOptions = new JWTTokenOptions(); builder.Configuration.Bind("JWTTokenOptions", tokenOptions); builder.Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//Bearer Scheme .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { //JWT有一些默认的属性,就是给鉴权时就可以筛选了 ValidateIssuer = true,//是否验证Issuer ValidateAudience = true,//是否验证Audience ValidateLifetime = true,//是否验证失效时间---默认还添加了300s后才过期 ClockSkew = TimeSpan.FromSeconds(0),//token过期后立马过期 ValidateIssuerSigningKey = true,//是否验证SecurityKey ValidAudience = tokenOptions.Audience,//Audience,需要跟前面签发jwt的设置一致 ValidIssuer = tokenOptions.Issuer,//Issuer,这两项和前面签发jwt的设置一致 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.SecurityKey)),//拿到SecurityKey }; }); #endregion jwt校验 HS var app = builder.Build(); // Configure the HTTP request pipeline. app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "CommentMicroService V1")); app.UsePerOptionsRequest(); app.UseHealthCheckMiddleware(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.UseConsulConfiguration(builder.Configuration).Wait(); app.Run();
这篇关于ASP.NET Core Ocelot+Consul+Nginx+JWT 构建微服务鉴权中心的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#