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
- 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 _logger = null;
private IJWTService _iJWTService = null;
private readonly IConfiguration _iConfiguration;
private HttpHelperService _HttpHelperService = null;
public AuthenticationController(ILoggerFactory factory,
ILogger 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 Get()
{
return new List() { 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
{
///
/// 主键ID
///
public long Id { get; set; }
///
/// 创建时间
///
public DateTime CreateTime { get; set; } = DateTime.Now;
///
/// 修改时间
///
public DateTime UpdateTime { get; set; } = DateTime.Now;
///
/// 用户名
///
public string UserName { get; set; } = string.Empty;
///
/// 密码
///
public string Password { get; set; } = string.Empty;
///
/// 用户昵称
///
public string NickName { get; set; } = string.Empty;
///
/// 用户部门ID
///
public long DepartmentId { get; set; } = -1;
///
/// 用户头像
///
public string Avatar { get; set; } = string.Empty;
///
/// 是否是老师
///
public bool IsTeacher { get; set; } = false;
///
/// 用户规则ID 测试期间 方便测试暂不关联规则表 -1表示普通用户具有查询权限 0代表管理员具有增加 删除 修改权限
///
public long RoleId { get; set; } = -1;
}
RSA 文件夹
RSAHelper.cs
public class RSAHelper
{
///
/// 从本地文件中读取用来签发 Token 的 RSA Key
///
/// 存放密钥的文件夹路径
///
///
///
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(File.ReadAllText(fileTotalPath));
return true;
}
}
///
/// 生成并保存 RSA 公钥与私钥
///
/// 存放密钥的文件夹路径
///
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
///
/// 就是去调用服务的---暂时没有Consul---ToDo
///
public class HttpHelperService
{
#region Option注入
private readonly ConfigInformation _ConfigInformation;
public HttpHelperService(IOptionsMonitor 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(content);
User user = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(response.Data));
return user;
}
else
{
return null;
}
}
public HttpResponseMessage HttpRequest(string url, HttpMethod httpMethod, Dictionary 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
///
/// 封装注入
///
public interface IJWTService
{
///
/// 获取Token
///
/// 账号
/// 密码
/// 用户信息
///
string GetToken(string UserName, string password, User user);
}
JWTHSService.cs
public class JWTHSService : IJWTService
{
#region Option注入
private readonly JWTTokenOptions _JWTTokenOptions;
public JWTHSService(IOptionsMonitor 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)
{
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(builder.Configuration.GetSection("ConfigInformation"));
builder.Services.AddTransient();
builder.Services.AddControllers();
#region HS256
builder.Services.AddScoped();
//builder.Services.Configure(builder.Configuration.GetSection("JWTTokenOptions"));
#endregion HS256
#region RS256
//builder.Services.AddScoped();
//builder.Services.Configure(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();
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(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();
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 服务注入
///
/// 分页获取数据
///
///
///
///
[HttpGet("page")]
public HttpJsonResponse GetPaged(int pageIndex = 1, int pageSize = 10)
{
var data = _lessonService?.GetLessons(pageIndex, pageSize, l => l.CreateTime);
return HttpJsonResponse.SuccessResult(data);
}
///
/// 创建课程
///
///
///
[HttpPost("create")]
[Authorize(Roles = "0")]
public HttpJsonResponse Create(Lesson lesson)
{
var data = _lessonService?.CreateLesson(lesson);
return HttpJsonResponse.SuccessResult(data);
}
///
/// 按条件筛选数据
///
///
///
[HttpPost("filter")]
public HttpJsonResponse GetPagedByFilter([FromBody] LessonFilter filter)
{
var data = _lessonService?.PagedLessonsByFilter(filter.GetFilterExpression(),
filter.CategoryId, filter.PageIndex, filter.PageSize);
return HttpJsonResponse.SuccessResult(data);
}
///
/// 按照Id删除数据
///
///
///
[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("删除课程失败!");
}
///
/// 更新数据
///
///
///
[HttpPut("update")]
[Authorize(Roles = "0")]
public HttpJsonResponse Update(Lesson lesson)
{
var data = _lessonService?.Update(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();
#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();