322 lines
14 KiB
C#
322 lines
14 KiB
C#
using CSRedis;
|
||
using System.IO;
|
||
using Microsoft.AspNetCore.DataProtection;
|
||
using Microsoft.Extensions.Hosting;
|
||
using Microsoft.AspNetCore.Builder;
|
||
using Microsoft.AspNetCore.Hosting;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using WaterCloud.Code;
|
||
using WaterCloud.Code.Model;
|
||
using System.Text.Encodings.Web;
|
||
using System.Text.Unicode;
|
||
using Newtonsoft.Json.Serialization;
|
||
using WaterCloud.Service.AutoJob;
|
||
using WaterCloud.DataBase;
|
||
using System.Reflection;
|
||
using System.Linq;
|
||
using WaterCloud.Service;
|
||
using Autofac;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Quartz;
|
||
using Quartz.Impl;
|
||
using Quartz.Spi;
|
||
using System;
|
||
using Chloe.Infrastructure.Interception;
|
||
using Microsoft.Extensions.FileProviders;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.AspNetCore.ResponseCompression;
|
||
using System.IO.Compression;
|
||
using WaterCloud.Domain.SystemOrganize;
|
||
using Microsoft.OpenApi.Models;
|
||
using System.Collections.Generic;
|
||
|
||
namespace WaterCloud.Web
|
||
{
|
||
public class Startup
|
||
{
|
||
public IConfiguration Configuration { get; }
|
||
public IWebHostEnvironment WebHostEnvironment { get; set; }
|
||
public Startup(IConfiguration configuration, IWebHostEnvironment env)
|
||
{
|
||
Configuration = configuration;
|
||
WebHostEnvironment = env;
|
||
GlobalContext.LogWhenStart(env);
|
||
GlobalContext.HostingEnvironment = env;
|
||
}
|
||
// This method gets called by the runtime. Use this method to add services to the container.
|
||
public async void ConfigureServices(IServiceCollection services)
|
||
{
|
||
GlobalContext.SystemConfig = Configuration.GetSection("SystemConfig").Get<SystemConfig>();
|
||
GlobalContext.Services = services;
|
||
GlobalContext.Configuration = Configuration;
|
||
services.AddSwaggerGen(config =>
|
||
{
|
||
config.SwaggerDoc("v1", new OpenApiInfo { Title = "WaterCloud Api", Version = "v1" });
|
||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||
config.IncludeXmlComments(xmlPath, true); //添加控制器层注释(true表示显示控制器注释)
|
||
config.AddSecurityDefinition(GlobalContext.SystemConfig.TokenName, new OpenApiSecurityScheme
|
||
{
|
||
Description = "header token",
|
||
Name = GlobalContext.SystemConfig.TokenName,
|
||
In = ParameterLocation.Header,
|
||
Scheme = "",
|
||
Type = SecuritySchemeType.ApiKey,//设置类型
|
||
BearerFormat = ""
|
||
});
|
||
config.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||
{
|
||
{
|
||
new OpenApiSecurityScheme
|
||
{
|
||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = GlobalContext.SystemConfig.TokenName }
|
||
},
|
||
new List<string>()
|
||
}
|
||
});
|
||
});
|
||
services.AddSession();
|
||
//代替HttpContext.Current
|
||
services.AddHttpContextAccessor();
|
||
//缓存缓存选择
|
||
if (Configuration.GetSection("SystemConfig:CacheProvider").Value!= Define.CACHEPROVIDER_REDIS)
|
||
{
|
||
services.AddMemoryCache();
|
||
}
|
||
else
|
||
{
|
||
//redis 注入服务
|
||
string redisConnectiong = Configuration.GetSection("SystemConfig:RedisConnectionString").Value;
|
||
// 多客户端 1、基础 2、操作日志
|
||
var redisDB1 = new CSRedisClient(redisConnectiong + ",defaultDatabase=" + 0);
|
||
BaseHelper.Initialization(redisDB1);
|
||
var redisDB2 = new CSRedisClient(redisConnectiong + ",defaultDatabase=" + 1);
|
||
HandleLogHelper.Initialization(redisDB2);
|
||
services.AddSingleton(redisDB1);
|
||
services.AddSingleton(redisDB2);
|
||
}
|
||
//连续guid初始化,示例IDGenerator.NextId()
|
||
services.AddSingleton<IDistributedIDGenerator, SequentialGuidIDGenerator>();
|
||
#region 依赖注入
|
||
//注入数据库连接
|
||
services.AddScoped<Chloe.IDbContext>((serviceProvider) =>
|
||
{
|
||
return DBContexHelper.Contex();
|
||
});
|
||
#region 注入 Quartz调度类
|
||
services.AddSingleton<JobExecute>();
|
||
//注册ISchedulerFactory的实例。
|
||
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
|
||
services.AddSingleton<IJobFactory, IOCJobFactory>();
|
||
//是否开启后台任务
|
||
if (Configuration.GetSection("SystemConfig:OpenQuarz").Value == "True")
|
||
{
|
||
services.AddHostedService<JobCenter>();
|
||
}
|
||
#endregion
|
||
//注入SignalR实时通讯,默认用json传输
|
||
services.AddSignalR(options =>
|
||
{
|
||
//客户端发保持连接请求到服务端最长间隔,默认30秒,改成4分钟,网页需跟着设置connection.keepAliveIntervalInMilliseconds = 12e4;即2分钟
|
||
options.ClientTimeoutInterval = TimeSpan.FromMinutes(4);
|
||
//服务端发保持连接请求到客户端间隔,默认15秒,改成2分钟,网页需跟着设置connection.serverTimeoutInMilliseconds = 24e4;即4分钟
|
||
options.KeepAliveInterval = TimeSpan.FromMinutes(2);
|
||
});
|
||
////注册html解析
|
||
//services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));
|
||
////注册特性
|
||
//services.AddScoped<HandlerLoginAttribute>();
|
||
//services.AddScoped<HandlerAuthorizeAttribute>();
|
||
////ajax不能使用注入
|
||
////services.AddScoped<HandlerAjaxOnlyAttribute>();
|
||
//services.AddScoped<HandlerAdminAttribute>();
|
||
#endregion
|
||
services.AddCors(options => options.AddPolicy("CorsPolicy",
|
||
builder =>
|
||
{
|
||
builder.AllowAnyMethod().AllowAnyHeader()
|
||
.WithOrigins(Configuration.GetSection("SystemConfig:AllowCorsSite").Value.Split(","))
|
||
.AllowCredentials();
|
||
}));
|
||
services.AddHttpClient();
|
||
services.AddControllersWithViews(options =>
|
||
{
|
||
options.Filters.Add<GlobalExceptionFilter>();
|
||
options.Filters.Add<ModelActionFilter>();
|
||
options.ModelMetadataDetailsProviders.Add(new ModelBindingMetadataProvider());
|
||
//options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
||
}).AddNewtonsoftJson(options =>
|
||
{
|
||
// 返回数据首字母不小写,CamelCasePropertyNamesContractResolver是小写
|
||
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
|
||
}).AddControllersAsServices().AddRazorRuntimeCompilation();
|
||
services.AddDirectoryBrowser();
|
||
services.AddControllers(options =>
|
||
{
|
||
options.Filters.Add<ModelActionFilter>();
|
||
options.ModelMetadataDetailsProviders.Add(new ModelBindingMetadataProvider());
|
||
}).ConfigureApiBehaviorOptions(options =>
|
||
{
|
||
options.SuppressModelStateInvalidFilter = true;
|
||
});
|
||
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
|
||
//启用 Gzip 和 Brotil 压缩功能
|
||
services.AddResponseCompression(options =>
|
||
{
|
||
options.Providers.Add<BrotliCompressionProvider>();
|
||
options.Providers.Add<GzipCompressionProvider>();
|
||
options.MimeTypes =
|
||
ResponseCompressionDefaults.MimeTypes.Concat(
|
||
new[] { "image/svg+xml" });
|
||
});
|
||
|
||
services.Configure<BrotliCompressionProviderOptions>(options =>
|
||
{
|
||
options.Level = (CompressionLevel)4; // 4 or 5 is OK
|
||
});
|
||
services.AddOptions();
|
||
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(GlobalContext.HostingEnvironment.ContentRootPath + Path.DirectorySeparatorChar + "DataProtection"));
|
||
//更新数据库管理员和主系统
|
||
try
|
||
{
|
||
if (GlobalContext.SystemConfig.ReviseSysem == true)
|
||
{
|
||
using (var context = DBContexHelper.Contex())
|
||
{
|
||
var setentity = context.Query<SystemSetEntity>().FirstOrDefault();
|
||
context.Session.BeginTransaction();
|
||
var user = context.Query<UserEntity>().Where(a => a.F_Account == setentity.F_AdminAccount).FirstOrDefault();
|
||
var userinfo = context.Query<UserLogOnEntity>().Where(a => a.F_UserId == user.F_Id).FirstOrDefault();
|
||
userinfo.F_UserSecretkey = Md5.md5(Utils.CreateNo(), 16).ToLower();
|
||
userinfo.F_UserPassword = Md5.md5(DESEncrypt.Encrypt(Md5.md5(GlobalContext.SystemConfig.SysemUserPwd, 32).ToLower(), userinfo.F_UserSecretkey).ToLower(), 32).ToLower();
|
||
context.Update<UserEntity>(a => a.F_Id == user.F_Id, a => new UserEntity
|
||
{
|
||
F_Account = GlobalContext.SystemConfig.SysemUserCode
|
||
});
|
||
var cacheKeyUser = "watercloud_userdata_";
|
||
await CacheHelper.Remove(cacheKeyUser + user.F_Id);
|
||
await context.UpdateAsync<UserLogOnEntity>(a => a.F_Id == userinfo.F_Id, a => new UserLogOnEntity
|
||
{
|
||
F_UserPassword = userinfo.F_UserPassword,
|
||
F_UserSecretkey = userinfo.F_UserSecretkey
|
||
});
|
||
await context.UpdateAsync<SystemSetEntity>(a => a.F_Id == userinfo.F_Id, a => new SystemSetEntity
|
||
{
|
||
F_AdminAccount = GlobalContext.SystemConfig.SysemUserCode,
|
||
F_AdminPassword = GlobalContext.SystemConfig.SysemUserPwd
|
||
});
|
||
context.Session.CommitTransaction();
|
||
var cacheKeyOperator = "watercloud_operator_";// +登录者token
|
||
await CacheHelper.Remove(cacheKeyOperator + "info_" + user.F_Id);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Write(ex);
|
||
}
|
||
//清理缓存
|
||
//CacheHelper.FlushAll().GetAwaiter().GetResult();
|
||
}
|
||
//AutoFac注入
|
||
public void ConfigureContainer(ContainerBuilder builder)
|
||
{
|
||
var assemblys = Assembly.Load("WaterCloud.Service");//Service是继承接口的实现方法类库名称
|
||
var baseType = typeof(IDenpendency);//IDenpendency 是一个接口(所有要实现依赖注入的借口都要继承该接口)
|
||
builder.RegisterAssemblyTypes(assemblys).Where(m => baseType.IsAssignableFrom(m) && m != baseType)
|
||
.InstancePerLifetimeScope()//生命周期,这里没有使用接口方式
|
||
.PropertiesAutowired() ;//属性注入
|
||
//Controller中使用属性注入
|
||
var controllerBaseType = typeof(Controller);
|
||
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
|
||
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
||
.PropertiesAutowired();
|
||
//注册html解析
|
||
builder.RegisterInstance(HtmlEncoder.Create(UnicodeRanges.All)).SingleInstance();
|
||
//注册特性
|
||
builder.RegisterType(typeof(HandlerLoginAttribute)).InstancePerLifetimeScope();
|
||
builder.RegisterType(typeof(HandlerAuthorizeAttribute)).InstancePerLifetimeScope();
|
||
builder.RegisterType(typeof(HandlerAdminAttribute)).InstancePerLifetimeScope();
|
||
builder.RegisterType(typeof(HandlerLockAttribute)).InstancePerLifetimeScope();
|
||
//ControllerBase中使用属性注入
|
||
controllerBaseType = typeof(ControllerBase);
|
||
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
|
||
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
||
.PropertiesAutowired();
|
||
//注册特性
|
||
builder.RegisterType(typeof(AuthorizeFilterAttribute)).InstancePerLifetimeScope();
|
||
builder.RegisterType(typeof(LoginFilterAttribute)).InstancePerLifetimeScope();
|
||
}
|
||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||
public void Configure(IApplicationBuilder app)
|
||
{
|
||
//由于.Net Core默认只会从wwwroot目录加载静态文件,其他文件夹的静态文件无法正常访问。
|
||
//而我们希望将图片上传到网站根目录的upload文件夹下,所以需要额外在Startup.cs类的Configure方法中
|
||
string resource = Path.Combine(Directory.GetCurrentDirectory(), "upload");
|
||
if (!FileHelper.IsExistDirectory(resource))
|
||
{
|
||
FileHelper.CreateFolder(resource);
|
||
}
|
||
app.UseStaticFiles(new StaticFileOptions
|
||
{
|
||
FileProvider = new PhysicalFileProvider(resource),
|
||
RequestPath = "/upload",
|
||
OnPrepareResponse = ctx =>
|
||
{
|
||
ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=36000");
|
||
}
|
||
});
|
||
app.UseCors("CorsPolicy");
|
||
if (WebHostEnvironment.IsDevelopment())
|
||
{
|
||
//打印sql
|
||
IDbCommandInterceptor interceptor = new DbCommandInterceptor();
|
||
DbInterception.Add(interceptor);
|
||
GlobalContext.SystemConfig.Debug = true;
|
||
app.UseDeveloperExceptionPage();
|
||
}
|
||
else
|
||
{
|
||
app.UseExceptionHandler("/Home/Error?msg=404");
|
||
}
|
||
//文件地址Resource
|
||
//静态资源wwwroot
|
||
app.UseStaticFiles(new StaticFileOptions
|
||
{
|
||
ContentTypeProvider = new CustomerFileExtensionContentTypeProvider(),
|
||
OnPrepareResponse = GlobalContext.SetCacheControl
|
||
});
|
||
//启用 Gzip 和 Brotil 压缩功能
|
||
app.UseResponseCompression();
|
||
app.Use(next => context =>
|
||
{
|
||
context.Request.EnableBuffering();
|
||
return next(context);
|
||
});
|
||
app.UseSwagger(c =>
|
||
{
|
||
c.RouteTemplate = "api-doc/{documentName}/swagger.json";
|
||
});
|
||
app.UseSwaggerUI(c =>
|
||
{
|
||
c.RoutePrefix = "api-doc";
|
||
c.SwaggerEndpoint("v1/swagger.json", "WaterCloud Api v1");
|
||
});
|
||
//session
|
||
app.UseSession();
|
||
//路径
|
||
app.UseRouting();
|
||
//MVC路由
|
||
app.UseEndpoints(endpoints =>
|
||
{
|
||
endpoints.MapHub<MessageHub>("/chatHub");
|
||
endpoints.MapControllerRoute("areas", "{area:exists}/{controller=Home}/{action=Index}/{id?}");
|
||
endpoints.MapControllerRoute("default", "{controller=Login}/{action=Index}/{id?}");
|
||
endpoints.MapControllerRoute("api", "api/{controller=ApiHome}/{action=Index}/{id?}");
|
||
});
|
||
GlobalContext.ServiceProvider = app.ApplicationServices;
|
||
}
|
||
}
|
||
}
|