添加项目文件。
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace IRaCIS.WX.CoreApi.Auth
|
||||
{
|
||||
public class AuthMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
public AuthMiddleware(RequestDelegate next, IEasyCachingProvider provider)
|
||||
{
|
||||
_next = next;
|
||||
_provider = provider;
|
||||
}
|
||||
/// <summary>
|
||||
///为了前端 一段时间无操作,需要重新登陆
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
|
||||
var isLogin = httpContext.Request.Path.ToString().ToLower().Contains("login");
|
||||
|
||||
var result = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
|
||||
|
||||
if (!isLogin)
|
||||
{
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
await httpContext.Response.WriteAsync("Unauthorized");
|
||||
}
|
||||
else
|
||||
{
|
||||
var toekn = result.Properties.Items[".Token.access_token"];
|
||||
var jwtHandler = new JwtSecurityTokenHandler();
|
||||
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(toekn);
|
||||
object userId;
|
||||
jwtToken.Payload.TryGetValue("id", out userId);
|
||||
|
||||
var cacheValueExist = await _provider.ExistsAsync(userId.ToString()); //Get<string>(userId.ToString()).ToString();
|
||||
if (!cacheValueExist)
|
||||
{
|
||||
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
await httpContext.Response.WriteAsync("Unauthorized");
|
||||
}
|
||||
else
|
||||
{
|
||||
await _provider.SetAsync(userId.ToString(), userId.ToString(), TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan));
|
||||
httpContext.User = result.Principal;
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
else await _next.Invoke(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
||||
|
||||
public static class HangfireConfig
|
||||
{
|
||||
|
||||
public static void UseHangfireConfig(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
app.UseHangfireDashboard("/api/hangfire", new DashboardOptions()
|
||||
{
|
||||
//直接访问,没有带token 获取不到用户身份信息,所以这种自定义授权暂时没法使用
|
||||
//Authorization = new[] { new hangfireAuthorizationFilter() }
|
||||
|
||||
//本地请求 才能看
|
||||
Authorization = new[] { new LocalRequestsOnlyAuthorizationFilter() }
|
||||
|
||||
});
|
||||
|
||||
#region hangfire
|
||||
//// 延迟任务执行 1秒之后执行 有时启动没运行 换成添加到队列中
|
||||
//BackgroundJob.Schedule<ICacheTrialStatusJob>(t => t.MemoryCacheTrialStatus(), TimeSpan.FromSeconds(1));
|
||||
////添加到后台任务队列,
|
||||
//BackgroundJob.Enqueue<ICacheTrialStatusJob>(t => t.MemoryCacheTrialStatus());
|
||||
|
||||
//周期性任务,1天执行一次
|
||||
RecurringJob.AddOrUpdate<ICacheTrialStatusJob>(t => t.MemoryCacheTrialStatus(), Cron.Daily);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Hangfire.Dashboard;
|
||||
|
||||
namespace IRaCIS.Core.API.Filter
|
||||
{
|
||||
public class hangfireAuthorizationFilter : IDashboardAuthorizationFilter
|
||||
{
|
||||
public bool Authorize(DashboardContext context)
|
||||
{
|
||||
var httpContext = context.GetHttpContext();
|
||||
|
||||
// Allow all authenticated users to see the Dashboard (potentially dangerous).
|
||||
return httpContext.User.Identity.IsAuthenticated;
|
||||
|
||||
//return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using System.IO;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class IRacisHostFileStore
|
||||
{
|
||||
|
||||
public static void UseIRacisHostStaticFileStore(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
|
||||
var uploadPath = Path.Combine(Directory.GetParent(env.ContentRootPath.TrimEnd('\\')).FullName, StaticData.UploadFileFolder);
|
||||
var dicomPath = Path.Combine(Directory.GetParent(env.ContentRootPath.TrimEnd('\\')).FullName, StaticData.TrialDataFolder);
|
||||
|
||||
|
||||
if (!Directory.Exists(uploadPath))
|
||||
{
|
||||
Directory.CreateDirectory(uploadPath);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(dicomPath))
|
||||
{
|
||||
Directory.CreateDirectory(dicomPath);
|
||||
}
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(uploadPath),
|
||||
RequestPath = $"/{StaticData.UploadFileFolder}"
|
||||
});
|
||||
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(dicomPath),
|
||||
RequestPath = $"/{StaticData.TrialDataFolder}"
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class LocalizationConfig
|
||||
{
|
||||
|
||||
public static void UseLocalization(this IApplicationBuilder app)
|
||||
{
|
||||
var supportedCultures = new List<CultureInfo>
|
||||
{
|
||||
new CultureInfo("en-US"),
|
||||
new CultureInfo("zh-CN")
|
||||
};
|
||||
|
||||
var options = new RequestLocalizationOptions
|
||||
{
|
||||
//DefaultRequestCulture = new RequestCulture("en-US"),
|
||||
SupportedCultures = supportedCultures,
|
||||
SupportedUICultures = supportedCultures,
|
||||
|
||||
ApplyCurrentCultureToResponseHeaders = true
|
||||
};
|
||||
|
||||
//options.RequestCultureProviders.RemoveAt(0);
|
||||
//options.RequestCultureProviders.RemoveAt(1);
|
||||
|
||||
app.UseRequestLocalization(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using LogDashboard;
|
||||
using LogDashboard.Authorization;
|
||||
|
||||
namespace IRaCIS.Core.API.Filter
|
||||
{
|
||||
|
||||
public class LogDashBoardAuthFilter : ILogDashboardAuthorizationFilter
|
||||
{
|
||||
//在此可以利用 本系统的UerTypeEnum 判断
|
||||
public bool Authorization(LogDashboardContext context)
|
||||
{
|
||||
return context.HttpContext.User.Identity.IsAuthenticated;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Serilog;
|
||||
using Serilog.Context;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.API._PipelineExtensions.Serilog
|
||||
{
|
||||
public class RequestResponseLoggingMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public RequestResponseLoggingMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
var ContentType = context.Request.ContentType;
|
||||
|
||||
var isUploadRelation = false;
|
||||
|
||||
if (ContentType != null)
|
||||
{
|
||||
isUploadRelation = context.Request.ContentType.Contains("multipart/form-data") || context.Request.ContentType.Contains("boundary");
|
||||
}
|
||||
|
||||
|
||||
if (isUploadRelation)
|
||||
{
|
||||
using (LogContext.PushProperty("RequestBody", string.Empty))
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var requestBodyPayload = await ReadRequestBody(context.Request);
|
||||
|
||||
using (LogContext.PushProperty("RequestBody", requestBodyPayload))
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
}
|
||||
|
||||
//var request = context.Request;
|
||||
|
||||
|
||||
// Read and log request body data
|
||||
|
||||
//SerilogHelper.RequestPayload = requestBodyPayload;
|
||||
|
||||
#region ResponseBody
|
||||
|
||||
//// Read and log response body data
|
||||
//// Copy a pointer to the original response body stream
|
||||
//var originalResponseBodyStream = context.Response.Body;
|
||||
|
||||
//// Create a new memory stream...
|
||||
//using (var responseBody = new MemoryStream())
|
||||
//{
|
||||
// // ...and use that for the temporary response body
|
||||
// context.Response.Body = responseBody;
|
||||
|
||||
// // Continue down the Middleware pipeline, eventually returning to this class
|
||||
//await _next(context);
|
||||
|
||||
// // Copy the contents of the new memory stream (which contains the response) to the original stream, which is then returned to the client.
|
||||
// await responseBody.CopyToAsync(originalResponseBodyStream);
|
||||
//}
|
||||
//string responseBodyPayload = await ReadResponseBody(context.Response);
|
||||
//_diagnosticContext.Set("ResponseBody", responseBodyPayload);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async Task<string> ReadRequestBody(HttpRequest request)
|
||||
{
|
||||
// Ensure the request's body can be read multiple times (for the next middlewares in the pipeline).
|
||||
request.EnableBuffering();
|
||||
|
||||
using var streamReader = new StreamReader(request.Body, leaveOpen: true);
|
||||
var requestBody = await streamReader.ReadToEndAsync();
|
||||
|
||||
// Reset the request's body stream position for next middleware in the pipeline.
|
||||
request.Body.Position = 0;
|
||||
return requestBody == null ? String.Empty : requestBody.Trim();
|
||||
}
|
||||
|
||||
private static async Task<string> ReadResponseBody(HttpResponse response)
|
||||
{
|
||||
response.Body.Seek(0, SeekOrigin.Begin);
|
||||
string responseBody = await new StreamReader(response.Body).ReadToEndAsync();
|
||||
response.Body.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
return $"{responseBody}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using IRaCIS.Core.API._PipelineExtensions.Serilog;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Serilog;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
||||
|
||||
public static class SerilogConfig
|
||||
{
|
||||
|
||||
public static void UseSerilogConfig(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
app.UseMiddleware<RequestResponseLoggingMiddleware>();
|
||||
|
||||
app.UseSerilogRequestLogging(opts
|
||||
=>
|
||||
{
|
||||
opts.MessageTemplate = "{TokenUserRealName} {TokenUserType} {ClientIp} {RequestIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||
opts.EnrichDiagnosticContext = SerilogHelper.EnrichFromRequest;
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class SerilogHelper
|
||||
{
|
||||
//public static string RequestPayload = "";
|
||||
|
||||
public static void EnrichFromRequest(IDiagnosticContext diagnosticContext, HttpContext httpContext)
|
||||
{
|
||||
var request = httpContext.Request;
|
||||
|
||||
// Set all the common properties available for every request
|
||||
diagnosticContext.Set("Host", request.Host);
|
||||
|
||||
//这种获取的Ip不准 配置服务才行
|
||||
diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
|
||||
|
||||
//这种方式可以,但是serilog提供了 就不用了
|
||||
//diagnosticContext.Set("TestIP", httpContext.GetUserIp());
|
||||
|
||||
diagnosticContext.Set("Protocol", request.Protocol);
|
||||
diagnosticContext.Set("Scheme", request.Scheme);
|
||||
|
||||
//这种方式不行 读取的body为空字符串 必须在中间件中读取
|
||||
//diagnosticContext.Set("RequestBody", await ReadRequestBody(httpContext.Request));
|
||||
//diagnosticContext.Set("RequestBody", RequestPayload);
|
||||
|
||||
// Only set it if available. You're not sending sensitive data in a querystring right?!
|
||||
if (request.QueryString.HasValue)
|
||||
{
|
||||
diagnosticContext.Set("QueryString", request.QueryString.Value);
|
||||
}
|
||||
|
||||
// Set the content-type of the Response at this point
|
||||
diagnosticContext.Set("ContentType", httpContext.Response.ContentType);
|
||||
|
||||
diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst("realName")?.Value);
|
||||
|
||||
diagnosticContext.Set("TokenUserType", httpContext?.User?.FindFirst("userTypeEnumName")?.Value);
|
||||
|
||||
// Retrieve the IEndpointFeature selected for the request
|
||||
var endpoint = httpContext.GetEndpoint();
|
||||
if (endpoint is object) // endpoint != null
|
||||
{
|
||||
diagnosticContext.Set("EndpointName", endpoint.DisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user