using Autofac;
using Autofac.Extensions.DependencyInjection;
using Hangfire;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.IdentityModel.Tokens;
using StackExchange.Redis;
using Study.APPlication;
using Study.APPlication.Authen;
using Study.DoMain.IRepository;
using Study.EntityFrameworkCore;
using Study.EntityFrameworkCore.Repository;
using Study.EntityFrameworkCore.Seed;
using Study.Redis;
using StudyServer.HangfireTask;
using StudyServer.WebSockets;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
namespace StudyServer
{
public class Startup
{
public static ConnectionMultiplexer Redis;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
private static IContainer Container { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(
opt =>
{
opt.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
});
#region Hangfire
var HangfireConfig = Configuration.GetSection("HangfireConfig"); HangfireConfig hangfireConfig = new HangfireConfig(); hangfireConfig.ConnStr = HangfireConfig["ConnStr"]; int db = 0; int.TryParse(HangfireConfig["DB"], out db); hangfireConfig.DB = db; hangfireConfig.Prefix = HangfireConfig["Prefix"]; Redis = ConnectionMultiplexer.Connect(hangfireConfig.ConnStr); services.AddHangfire(config => config.UseRedisStorage(Redis, new Hangfire.Redis.RedisStorageOptions() { Db = hangfireConfig.DB, Prefix = hangfireConfig.Prefix }));
#endregion
#region 授权管理
var audienceConfig = Configuration.GetSection("Authentication"); var symmetricKeyAsBase64 = audienceConfig["SecurityKey"]; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); var signingKey = new SymmetricSecurityKey(keyByteArray); var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, ValidateIssuer = true, ValidIssuer = audienceConfig["Issuer"], ValidateAudience = true, ValidAudience = audienceConfig["Audience"], ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); //这个集合模拟用户权限表,可从数据库中查询出来 //如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名 var permissionRequirement = new PermissionRequirement("/api/denied", ClaimTypes.Role, audienceConfig["Issuer"], audienceConfig["Audience"], signingCredentials, new TimeSpan(24 * 365, 0, 0)); services.AddAuthorization(options => { options.AddPolicy("Permission", policy => policy.Requirements.Add(permissionRequirement)); }).AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o => { //不使用https o.RequireHttpsMetadata = false; o.TokenValidationParameters = tokenValidationParameters; }); //注入授权Handler services.AddSingleton(); services.AddSingleton(permissionRequirement);
#endregion
#region Swagger
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "WebAPI", Description = "框架集合", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { } }); // c.OperationFilter(); var basePath = PlatformServices.Default.Application.ApplicationBasePath; var xmlPath = Path.Combine(basePath, "API.XML"); c.IncludeXmlComments(xmlPath); //手动高亮 //添加header验证信息 //c.OperationFilter(); var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, }; c.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 c.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization",//jwt默认的参数名称 In = "header",//jwt默认存放Authorization信息的位置(请求头中) Type = "apiKey" }); });
#endregion
#region MySql
var connection = this.Configuration.GetValue<string>("ConnectionStrings"); services.AddDbContext(options => options.UseMySql(connection)); services.BuildServiceProvider().GetService ().Database.Migrate();
#endregion
#region 配置跨域
services.AddCors( options => options.AddPolicy( "Host", builder => builder .WithOrigins( Configuration["CorsOrigins"] .Split(",", StringSplitOptions.RemoveEmptyEntries) .ToArray() ) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() .SetPreflightMaxAge(TimeSpan.FromHours(1))//预检请求过期时间,用于减少OPTIONS请求 ) );
#endregion
StartTaskInit.InitTask(ref services);
#region Redis
var section = Configuration.GetSection("RedisConfig"); string _connectionString = section.GetSection("ConnIP").Value;//连接字符串 string _instanceName = section.GetSection("InstanceName").Value; //实例名称 int _defaultDB = int.Parse(section.GetSection("DB").Value ?? "0"); //默认数据库 services.AddSingleton(new RedisHelper(_connectionString, _instanceName, _defaultDB));
#endregion
#region 泛型依赖注入
var builders = new ContainerBuilder();//实例化 AutoFac 容器 builders.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency(); var assemblys = Assembly.Load("Study.APPlication");//Service是继承接口的实现方法类库名称 var baseType = typeof(IDependency);//IDependency 是一个接口(所有要实现依赖注入的借口都要继承该接口) builders.RegisterAssemblyTypes(assemblys) .Where(m => baseType.IsAssignableFrom(m) && m != baseType) .AsImplementedInterfaces().InstancePerLifetimeScope(); builders.Populate(services); Container = builders.Build();
#endregion
return new AutofacServiceProvider(Container);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, StudyDbContext context)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
#region Swagger
app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1"); });
#endregion
#region Hangfire
app.UseHangfireServer(); app.UseHangfireDashboard("/hangfire", new DashboardOptions() { //Authorization = new[] { new CustomAuthorizeFilter() } });
#endregion
app.UseCors("Host");
ServiceLocator.Instance = app.ApplicationServices;
//初始化数据
SeedHelper.SeenData(context);
//开启task任务
using (var scope = ServiceLocator.Instance.CreateScope()) { var ITask = scope.ServiceProvider.GetService(); ITask.Regist(); ITask.Run(); }
app.UseHttpsRedirection();
app.UseMvc();
app.Map("/ws", WebSocketXX.Map);
}
}
}