Merge branch 'master' into net7.0

This commit is contained in:
anjoy8 2023-11-14 09:25:04 +08:00
commit f786881e89
8 changed files with 572 additions and 311 deletions

View File

@ -15,324 +15,332 @@ using Serilog;
namespace Blog.Core.Controllers namespace Blog.Core.Controllers
{ {
/// <summary> /// <summary>
/// 登录管理【无权限】 /// 登录管理【无权限】
/// </summary> /// </summary>
[Produces("application/json")] [Produces("application/json")]
[Route("api/Login")] [Route("api/Login")]
[AllowAnonymous] [AllowAnonymous]
public class LoginController : BaseApiController public class LoginController : BaseApiController
{ {
readonly ISysUserInfoServices _sysUserInfoServices; readonly ISysUserInfoServices _sysUserInfoServices;
readonly IUserRoleServices _userRoleServices; readonly IUserRoleServices _userRoleServices;
readonly IRoleServices _roleServices; readonly IRoleServices _roleServices;
readonly PermissionRequirement _requirement; readonly PermissionRequirement _requirement;
private readonly IRoleModulePermissionServices _roleModulePermissionServices; private readonly IRoleModulePermissionServices _roleModulePermissionServices;
private readonly ILogger<LoginController> _logger; private readonly ILogger<LoginController> _logger;
/// <summary> /// <summary>
/// 构造函数注入 /// 构造函数注入
/// </summary> /// </summary>
/// <param name="sysUserInfoServices"></param> /// <param name="sysUserInfoServices"></param>
/// <param name="userRoleServices"></param> /// <param name="userRoleServices"></param>
/// <param name="roleServices"></param> /// <param name="roleServices"></param>
/// <param name="requirement"></param> /// <param name="requirement"></param>
/// <param name="roleModulePermissionServices"></param> /// <param name="roleModulePermissionServices"></param>
public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServices userRoleServices, public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServices userRoleServices,
IRoleServices roleServices, PermissionRequirement requirement, IRoleServices roleServices, PermissionRequirement requirement,
IRoleModulePermissionServices roleModulePermissionServices, ILogger<LoginController> logger) IRoleModulePermissionServices roleModulePermissionServices, ILogger<LoginController> logger)
{ {
this._sysUserInfoServices = sysUserInfoServices; this._sysUserInfoServices = sysUserInfoServices;
this._userRoleServices = userRoleServices; this._userRoleServices = userRoleServices;
this._roleServices = roleServices; this._roleServices = roleServices;
_requirement = requirement; _requirement = requirement;
_roleModulePermissionServices = roleModulePermissionServices; _roleModulePermissionServices = roleModulePermissionServices;
_logger = logger; _logger = logger;
} }
#region token的第1种方法 #region token的第1种方法
/// <summary> /// <summary>
/// 获取JWT的方法1 /// 获取JWT的方法1
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="pass"></param> /// <param name="pass"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[Route("Token")] [Route("Token")]
public async Task<MessageModel<string>> GetJwtStr(string name, string pass) public async Task<MessageModel<string>> GetJwtStr(string name, string pass)
{ {
string jwtStr = string.Empty; string jwtStr = string.Empty;
bool suc = false; bool suc = false;
//这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作 //这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass)); var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
if (user != null) if (user != null)
{ {
TokenModelJwt tokenModel = new TokenModelJwt {Uid = 1, Role = user}; TokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = user };
jwtStr = JwtHelper.IssueJwt(tokenModel); jwtStr = JwtHelper.IssueJwt(tokenModel);
suc = true; suc = true;
} }
else else
{ {
jwtStr = "login fail!!!"; jwtStr = "login fail!!!";
} }
return new MessageModel<string>() return new MessageModel<string>()
{ {
success = suc, success = suc,
msg = suc ? "获取成功" : "获取失败", msg = suc ? "获取成功" : "获取失败",
response = jwtStr response = jwtStr
}; };
} }
/// <summary> /// <summary>
/// 获取JWT的方法2给Nuxt提供 /// 获取JWT的方法2给Nuxt提供
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="pass"></param> /// <param name="pass"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[Route("GetTokenNuxt")] [Route("GetTokenNuxt")]
public MessageModel<string> GetJwtStrForNuxt(string name, string pass) public MessageModel<string> GetJwtStrForNuxt(string name, string pass)
{ {
string jwtStr = string.Empty; string jwtStr = string.Empty;
bool suc = false; bool suc = false;
//这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作 //这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
//这里直接写死了 //这里直接写死了
if (name == "admins" && pass == "admins") if (name == "admins" && pass == "admins")
{ {
TokenModelJwt tokenModel = new TokenModelJwt TokenModelJwt tokenModel = new TokenModelJwt
{ {
Uid = 1, Uid = 1,
Role = "Admin" Role = "Admin"
}; };
jwtStr = JwtHelper.IssueJwt(tokenModel); jwtStr = JwtHelper.IssueJwt(tokenModel);
suc = true; suc = true;
} }
else else
{ {
jwtStr = "login fail!!!"; jwtStr = "login fail!!!";
} }
var result = new var result = new
{ {
data = new {success = suc, token = jwtStr} data = new { success = suc, token = jwtStr }
}; };
return new MessageModel<string>() return new MessageModel<string>()
{ {
success = suc, success = suc,
msg = suc ? "获取成功" : "获取失败", msg = suc ? "获取成功" : "获取失败",
response = jwtStr response = jwtStr
}; };
} }
#endregion #endregion
/// <summary> /// <summary>
/// 获取JWT的方法3整个系统主要方法 /// 获取JWT的方法3整个系统主要方法
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="pass"></param> /// <param name="pass"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[Route("JWTToken3.0")] [Route("JWTToken3.0")]
public async Task<MessageModel<TokenInfoViewModel>> GetJwtToken3(string name = "", string pass = "") public async Task<MessageModel<TokenInfoViewModel>> GetJwtToken3(string name = "", string pass = "")
{
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass)) {
return Failed<TokenInfoViewModel>("用户名或密码不能为空"); string jwtStr = string.Empty;
pass = MD5Helper.MD5Encrypt32(pass); if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
return Failed<TokenInfoViewModel>("用户名或密码不能为空");
var user = await _sysUserInfoServices.Query(d => pass = MD5Helper.MD5Encrypt32(pass);
d.LoginName == name && d.LoginPWD == pass && d.IsDeleted == false);
if (user.Count > 0) var user = await _sysUserInfoServices.Query(d =>
{ d.LoginName == name && d.LoginPWD == pass && d.IsDeleted == false);
var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass); if (user.Count > 0)
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色 {
var claims = new List<Claim> var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass);
{ //如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
new Claim(ClaimTypes.Name, name), var claims = new List<Claim>
new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()), {
new Claim("TenantId", user.FirstOrDefault().TenantId.ToString()), new Claim(ClaimTypes.Name, name),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()), new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()),
new Claim(ClaimTypes.Expiration, new Claim("TenantId", user.FirstOrDefault().TenantId.ToString()),
DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
}; new Claim(ClaimTypes.Expiration,
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s))); DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
};
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
// ids4和jwt切换 // ids4和jwt切换
// jwt // jwt
if (!Permissions.IsUseIds4) if (!Permissions.IsUseIds4)
{ {
var data = await _roleModulePermissionServices.RoleModuleMaps(); var data = await _roleModulePermissionServices.RoleModuleMaps();
var list = (from item in data var list = (from item in data
where item.IsDeleted == false where item.IsDeleted == false
orderby item.Id orderby item.Id
select new PermissionItem select new PermissionItem
{ {
Url = item.Module?.LinkUrl, Url = item.Module?.LinkUrl,
Role = item.Role?.Name.ObjToString(), Role = item.Role?.Name.ObjToString(),
}).ToList(); }).ToList();
_requirement.Permissions = list; _requirement.Permissions = list;
} }
var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement); var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
return Success(token, "获取成功"); return Success(token, "获取成功");
} }
else else
{ {
return Failed<TokenInfoViewModel>("认证失败"); return Failed<TokenInfoViewModel>("认证失败");
} }
} }
/// <summary> [HttpGet]
/// 请求刷新Token以旧换新 [Route("GetJwtTokenSecret")]
/// </summary> public async Task<MessageModel<TokenInfoViewModel>> GetJwtTokenSecret(string name = "", string pass = "")
/// <param name="token"></param> {
/// <returns></returns> var rlt = await GetJwtToken3(name, pass);
[HttpGet] return rlt;
[Route("RefreshToken")] }
public async Task<MessageModel<TokenInfoViewModel>> RefreshToken(string token = "")
{
string jwtStr = string.Empty;
if (string.IsNullOrEmpty(token)) /// <summary>
return Failed<TokenInfoViewModel>("token无效请重新登录"); /// 请求刷新Token以旧换新
var tokenModel = JwtHelper.SerializeJwt(token); /// </summary>
if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0) /// <param name="token"></param>
{ /// <returns></returns>
var user = await _sysUserInfoServices.QueryById(tokenModel.Uid); [HttpGet]
var value = User.Claims.SingleOrDefault(s => s.Type == JwtRegisteredClaimNames.Iat)?.Value; [Route("RefreshToken")]
if (value != null && user.CriticalModifyTime > value.ObjToDate()) public async Task<MessageModel<TokenInfoViewModel>> RefreshToken(string token = "")
{ {
return Failed<TokenInfoViewModel>("很抱歉,授权已失效,请重新授权!"); string jwtStr = string.Empty;
}
if (user != null && !(value != null && user.CriticalModifyTime > value.ObjToDate())) if (string.IsNullOrEmpty(token))
{ return Failed<TokenInfoViewModel>("token无效请重新登录");
var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD); var tokenModel = JwtHelper.SerializeJwt(token);
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色 if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0)
var claims = new List<Claim> {
{ var user = await _sysUserInfoServices.QueryById(tokenModel.Uid);
new Claim(ClaimTypes.Name, user.LoginName), var value = User.Claims.SingleOrDefault(s => s.Type == JwtRegisteredClaimNames.Iat)?.Value;
new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()), if (value != null && user.CriticalModifyTime > value.ObjToDate())
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()), {
new Claim(ClaimTypes.Expiration, return Failed<TokenInfoViewModel>("很抱歉,授权已失效,请重新授权!");
DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) }
};
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
//用户标识 if (user != null && !(value != null && user.CriticalModifyTime > value.ObjToDate()))
var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); {
identity.AddClaims(claims); var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD);
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.LoginName),
new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
new Claim(ClaimTypes.Expiration,
DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
};
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement); //用户标识
return Success(refreshToken, "获取成功"); var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
} identity.AddClaims(claims);
}
return Failed<TokenInfoViewModel>("认证失败!"); var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
} return Success(refreshToken, "获取成功");
}
}
/// <summary> return Failed<TokenInfoViewModel>("认证失败!");
/// 获取JWT的方法4给 JSONP 测试 }
/// </summary>
/// <param name="callBack"></param>
/// <param name="id"></param>
/// <param name="sub"></param>
/// <param name="expiresSliding"></param>
/// <param name="expiresAbsoulute"></param>
/// <returns></returns>
[HttpGet]
[Route("jsonp")]
public void Getjsonp(string callBack, long id = 1, string sub = "Admin", int expiresSliding = 30,
int expiresAbsoulute = 30)
{
TokenModelJwt tokenModel = new TokenModelJwt
{
Uid = id,
Role = sub
};
string jwtStr = JwtHelper.IssueJwt(tokenModel); /// <summary>
/// 获取JWT的方法4给 JSONP 测试
/// </summary>
/// <param name="callBack"></param>
/// <param name="id"></param>
/// <param name="sub"></param>
/// <param name="expiresSliding"></param>
/// <param name="expiresAbsoulute"></param>
/// <returns></returns>
[HttpGet]
[Route("jsonp")]
public void Getjsonp(string callBack, long id = 1, string sub = "Admin", int expiresSliding = 30,
int expiresAbsoulute = 30)
{
TokenModelJwt tokenModel = new TokenModelJwt
{
Uid = id,
Role = sub
};
string response = string.Format("\"value\":\"{0}\"", jwtStr); string jwtStr = JwtHelper.IssueJwt(tokenModel);
string call = callBack + "({" + response + "})";
Response.WriteAsync(call); string response = string.Format("\"value\":\"{0}\"", jwtStr);
} string call = callBack + "({" + response + "})";
Response.WriteAsync(call);
}
/// <summary> /// <summary>
/// 测试 MD5 加密字符串 /// 测试 MD5 加密字符串
/// </summary> /// </summary>
/// <param name="password"></param> /// <param name="password"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[Route("Md5Password")] [Route("Md5Password")]
public string Md5Password(string password = "") public string Md5Password(string password = "")
{ {
return MD5Helper.MD5Encrypt32(password); return MD5Helper.MD5Encrypt32(password);
} }
/// <summary> /// <summary>
/// swagger登录 /// swagger登录
/// </summary> /// </summary>
/// <param name="loginRequest"></param> /// <param name="loginRequest"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
[Route("/api/Login/swgLogin")] [Route("/api/Login/swgLogin")]
public async Task<dynamic> SwgLogin([FromBody] SwaggerLoginRequest loginRequest) public async Task<dynamic> SwgLogin([FromBody] SwaggerLoginRequest loginRequest)
{ {
if (loginRequest is null) if (loginRequest is null)
{ {
return new {result = false}; return new { result = false };
} }
try try
{ {
var result = await GetJwtToken3(loginRequest.name, loginRequest.pwd); var result = await GetJwtToken3(loginRequest.name, loginRequest.pwd);
if (result.success) if (result.success)
{ {
HttpContext.SuccessSwagger(); HttpContext.SuccessSwagger();
HttpContext.SuccessSwaggerJwt(result.response.token); HttpContext.SuccessSwaggerJwt(result.response.token);
return new {result = true}; return new { result = true };
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning(ex, "Swagger登录异常"); _logger.LogWarning(ex, "Swagger登录异常");
} }
return new {result = false}; return new { result = false };
} }
/// <summary> /// <summary>
/// weixin登录 /// weixin登录
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
[Route("wxLogin")] [Route("wxLogin")]
public dynamic WxLogin(string g = "", string token = "") public dynamic WxLogin(string g = "", string token = "")
{ {
return new {g, token}; return new { g, token };
} }
} }
public class SwaggerLoginRequest public class SwaggerLoginRequest
{ {
public string name { get; set; } public string name { get; set; }
public string pwd { get; set; } public string pwd { get; set; }
} }
} }

View File

@ -144,6 +144,9 @@ else
//app.UseHsts(); //app.UseHsts();
} }
app.UseEncryptionRequest();
app.UseEncryptionResponse();
app.UseExceptionHandlerMiddle(); app.UseExceptionHandlerMiddle();
app.UseIpLimitMiddle(); app.UseIpLimitMiddle();
app.UseRequestResponseLogMiddle(); app.UseRequestResponseLogMiddle();

View File

@ -265,6 +265,20 @@
}, },
"IpRateLimit": { "IpRateLimit": {
"Enabled": true "Enabled": true
},
"EncryptionResponse": {
"Enabled": true,
"AllApis": false,
"LimitApis": [
"/api/Login/GetJwtTokenSecret"
]
},
"EncryptionRequest": {
"Enabled": true,
"AllApis": false,
"LimitApis": [
"/api/Login/GetJwtTokenSecret"
]
} }
}, },
"IpRateLimiting": { "IpRateLimiting": {

View File

@ -7,29 +7,29 @@ namespace Blog.Core.Common.Extensions;
public static class HttpResponseExceptions public static class HttpResponseExceptions
{ {
public static string GetResponseBody(this HttpResponse response) public static string GetResponseBody(this HttpResponse response)
{ {
if (response is null) if (response is null)
{ {
return default; return string.Empty;
} }
if (response.Body is FluentHttpResponseStream responseBody) //原始HttpResponseStream 无法读取
{ //实际上只是个包装类,内部使用了HttpResponsePipeWriter write
response.Body.Position = 0; switch (response.Body)
//不关闭底层流 {
using StreamReader stream = new StreamReader(responseBody, leaveOpen: true); case FluentHttpResponseStream:
string body = stream.ReadToEnd(); case MemoryStream:
response.Body.Position = 0; {
return body; response.Body.Position = 0;
} using var stream = new StreamReader(response.Body, leaveOpen: true);
else var body = stream.ReadToEnd();
{ response.Body.Position = 0;
//原始HttpResponseStream 无法读取 return body;
//实际上只是个包装类,内部使用了HttpResponsePipeWriter write }
throw new ApplicationException("The response body is not a FluentHttpResponseStream"); default:
} // throw new ApplicationException("The response body is not a FluentHttpResponseStream");
return string.Empty;
return default; }
} }
} }

View File

@ -0,0 +1,116 @@
using Blog.Core.Common;
using Blog.Core.Common.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Extensions
{
/// <summary>
/// 自定义中间件
/// 通过配置,对指定接口返回数据进行加密返回
/// 可过滤文件流
/// </summary>
public class EncryptionRequestMiddleware
{
private readonly RequestDelegate _next;
public EncryptionRequestMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// 配置开关,过滤接口
if (AppSettings.app("Middleware", "EncryptionRequest", "Enabled").ObjToBool())
{
var isAllApis = AppSettings.app("Middleware", "EncryptionRequest", "AllApis").ObjToBool();
var needEnApis = AppSettings.app<string>("Middleware", "EncryptionRequest", "LimitApis");
var path = context.Request.Path.Value.ToLower();
if (isAllApis || (path.Length > 5 && needEnApis.Any(d => d.ToLower().Contains(path))))
{
Console.WriteLine($"{isAllApis} -- {path}");
if (context.Request.Method.ToLower() == "post")
{
// 读取请求主体
using StreamReader reader = new(context.Request.Body, Encoding.UTF8);
string requestBody = await reader.ReadToEndAsync();
// 检查是否有要解密的数据
if (!string.IsNullOrEmpty(requestBody) && context.Request.Headers.ContainsKey("Content-Type") &&
context.Request.Headers["Content-Type"].ToString().ToLower().Contains("application/json"))
{
// 解密数据
string decryptedString = DecryptData(requestBody);
// 更新请求主体中的数据
context.Request.Body = GenerateStreamFromString(decryptedString);
}
}
else if (context.Request.Method.ToLower() == "get")
{
// 获取url参数
string param = context.Request.Query["param"];
// 检查是否有要解密的数据
if (!string.IsNullOrEmpty(param))
{
// 解密数据
string decryptedString = DecryptData(param);
// 更新url参数值
context.Request.QueryString = new QueryString($"?{decryptedString}");
}
}
await _next(context);
}
else
{
await _next(context);
}
}
else
{
await _next(context);
}
}
private string DecryptData(string encryptedData)
{
// 解密逻辑实现,可以根据你使用的加密算法和密钥进行自定义
byte[] bytes = Convert.FromBase64String(encryptedData);
string originalString = Encoding.UTF8.GetString(bytes);
Console.WriteLine(originalString);
return originalString;
}
private static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
public static class EncryptionRequestExtensions
{
/// <summary>
/// 自定义中间件
/// 通过配置,对指定接口入参进行解密操作
/// 注意:放到管道最外层
/// </summary>
public static IApplicationBuilder UseEncryptionRequest(this IApplicationBuilder builder)
{
return builder.UseMiddleware<EncryptionRequestMiddleware>();
}
}
}

View File

@ -0,0 +1,118 @@
using Blog.Core.Common;
using Blog.Core.Common.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Extensions
{
/// <summary>
/// 自定义中间件
/// 通过配置,对指定接口返回数据进行加密返回
/// 可过滤文件流
/// </summary>
public class EncryptionResponseMiddleware
{
private readonly RequestDelegate _next;
public EncryptionResponseMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// 配置开关,过滤接口
if (AppSettings.app("Middleware", "EncryptionResponse", "Enabled").ObjToBool())
{
var isAllApis = AppSettings.app("Middleware", "EncryptionResponse", "AllApis").ObjToBool();
var needEnApis = AppSettings.app<string>("Middleware", "EncryptionResponse", "LimitApis");
var path = context.Request.Path.Value.ToLower();
if (isAllApis || (path.Length > 5 && needEnApis.Any(d => d.ToLower().Contains(path))))
{
Console.WriteLine($"{isAllApis} -- {path}");
var responseCxt = context.Response;
var originalBodyStream = responseCxt.Body;
// 创建一个新的内存流用于存储加密后的数据
using var encryptedBodyStream = new MemoryStream();
// 用新的内存流替换 responseCxt.Body
responseCxt.Body = encryptedBodyStream;
// 执行下一个中间件请求管道
await _next(context);
//encryptedBodyStream.Seek(0, SeekOrigin.Begin);
//encryptedBodyStream.Position = 0;
// 可以去掉某些流接口
if (!context.Response.ContentType.ToLower().Contains("application/json"))
{
Console.WriteLine($"非json返回格式 {context.Response.ContentType}");
//await encryptedBodyStream.CopyToAsync(originalBodyStream);
context.Response.Body = originalBodyStream;
return;
}
// 读取加密后的数据
//var encryptedBody = await new StreamReader(encryptedBodyStream).ReadToEndAsync();
var encryptedBody = responseCxt.GetResponseBody();
if (encryptedBody.IsNotEmptyOrNull())
{
dynamic jsonObject = JsonConvert.DeserializeObject(encryptedBody);
string statusCont = jsonObject.status;
var status = statusCont.ObjToInt();
string msg = jsonObject.msg;
string successCont = jsonObject.success;
var success = successCont.ObjToBool();
dynamic responseCnt = success ? jsonObject.response : "";
string s = "1";
// 这里换成自己的任意加密方式
var response = responseCnt.ToString() != "" ? Convert.ToBase64String(Encoding.UTF8.GetBytes(responseCnt.ToString())) : "";
string resJson = JsonConvert.SerializeObject(new { response, msg, status, s, success });
context.Response.Clear();
responseCxt.ContentType = "application/json";
//await using var streamlriter = new StreamWriter(originalBodyStream, leaveOpen: true);
//await streamlriter.WriteAsync(resJson);
var encryptedData = Encoding.UTF8.GetBytes(resJson);
responseCxt.ContentLength = encryptedData.Length;
await originalBodyStream.WriteAsync(encryptedData, 0, encryptedData.Length);
responseCxt.Body = originalBodyStream;
}
}
else
{
await _next(context);
}
}
else
{
await _next(context);
}
}
}
public static class EncryptionResponseExtensions
{
/// <summary>
/// 自定义中间件
/// 通过配置,对指定接口返回数据进行加密返回
/// 可过滤文件流
/// 注意:放到管道最外层
/// </summary>
public static IApplicationBuilder UseEncryptionResponse(this IApplicationBuilder builder)
{
return builder.UseMiddleware<EncryptionResponseMiddleware>();
}
}
}

View File

@ -96,11 +96,11 @@ namespace Blog.Core.Extensions.Middlewares
// 去除 Html // 去除 Html
var reg = "<[^>]+>"; var reg = "<[^>]+>";
var isHtml = Regex.IsMatch(responseBody, reg);
if (!string.IsNullOrEmpty(responseBody)) if (!string.IsNullOrEmpty(responseBody))
{ {
Parallel.For(0, 1, e => var isHtml = Regex.IsMatch(responseBody, reg);
Parallel.For(0, 1, e =>
{ {
//LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody }); //LogLock.OutSql2Log("RequestResponseLog", new string[] { "Response Data:", ResponseBody });
LogLock.OutLogAOP("RequestResponseLog", response.HttpContext.TraceIdentifier, LogLock.OutLogAOP("RequestResponseLog", response.HttpContext.TraceIdentifier,

View File

@ -83,10 +83,12 @@ namespace Blog.Core.Extensions
{ {
BaseDBConfig.MainConfig = config; BaseDBConfig.MainConfig = config;
} }
else if (m.ConnId.ToLower().StartsWith(MainDb.CurrentDbConnId.ToLower()))
//复用连接 {
if (m.ConnId.ToLower().StartsWith(MainDb.CurrentDbConnId.ToLower())) //复用连接
BaseDBConfig.ReuseConfigs.Add(config); BaseDBConfig.ReuseConfigs.Add(config);
}
BaseDBConfig.ValidConfig.Add(config); BaseDBConfig.ValidConfig.Add(config);
} }