using Pomelo.EntityFrameworkCore; using System.Text; using AcaMate.Common.Chat; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using AcaMate.Common.Models; using AcaMate.V1.Services; using AcaMate.Common.Data; using AcaMate.Common.Token; using AcaMate.V1.Controllers; using AcaMate.V1.Models; var builder = WebApplication.CreateBuilder(args); // DB 설정부 시작 builder.Configuration.AddJsonFile("private/dbSetting.json", optional: true, reloadOnChange: true); // var connectionString = builder.Configuration.GetConnectionString("MariaDbConnection"); // builder.Services.AddDbContext(options => options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); builder.Services.AddDbContext(optionsAction: (serviceProvider, options) => { var httpContextAccessor = serviceProvider.GetRequiredService(); var dbName = httpContextAccessor.HttpContext?.Request.Query["aca_code"].ToString(); var baseConnectionString = builder.Configuration.GetConnectionString("MariaDbConnection"); if (!string.IsNullOrEmpty(dbName)) { baseConnectionString = baseConnectionString.Replace("database=AcaMate", $"database={dbName}"); } options.UseMySql(baseConnectionString, ServerVersion.AutoDetect(baseConnectionString)); }); builder.Services.AddHttpContextAccessor(); // DB 설정부 끝 var dbString = builder.Configuration.GetConnectionString("MariaDbConnection"); var userString = builder.Configuration.GetConnectionString("DBAccount"); // JWT 설정부 시작 if (builder.Environment.IsDevelopment()) { builder.Configuration.AddJsonFile("private/jwtSetting.Development.json", optional: true, reloadOnChange: true); } else { builder.Configuration.AddJsonFile("private/jwtSetting.json", optional: true, reloadOnChange: true); } builder.Services.Configure(builder.Configuration.GetSection("JwtSettings")); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { var jwtSettings = builder.Configuration.GetSection("JwtSettings").Get(); options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), ClockSkew = TimeSpan.FromMinutes(jwtSettings.ClockSkewMinutes) }; }); // JWT 설정부 끝 // PUSH 설정부 // 설정 바인딩 (appsettings.json의 "ApnsPushService" 섹션) builder.Services.Configure(builder.Configuration.GetSection("PushFileSetting")); // HttpClientFactory를 이용한 ApnsPushService 등록 (핸들러에 인증서 추가) builder.Services.AddHttpClient(client => { var settings = builder.Configuration.GetSection("PushFileSetting").Get(); client.BaseAddress = new Uri(settings.uri); client.Timeout = TimeSpan.FromSeconds(60); }) .ConfigurePrimaryHttpMessageHandler(() => { var config = builder.Configuration.GetSection("PushFileSetting").Get(); var handler = new HttpClientHandler(); // using var reader = new StreamReader(config.p12PWPath, new UTF8Encoding(false)); // var json = reader.ReadToEndAsync(); // p12PWPath 파일에서 비밀번호 읽어오기 (예시: JSON {"Password": "비밀번호"}) var json = File.ReadAllText(config.p12PWPath); var keys = JsonSerializer.Deserialize>(json); var certificate = new X509Certificate2(config.p12Path, keys["Password"]); handler.ClientCertificates.Add(certificate); handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12; return handler; }); // InMemoryPushQueue와 백그라운드 서비스 등록 builder.Services.AddSingleton(); builder.Services.AddHostedService(); // PUSH 설정부 끝 builder.Services.AddControllers(); // 여기다가 API 있는 컨트롤러들 AddScoped 하면 되는건가? builder.Services.AddScoped(); builder.Services.AddScoped(); // builder.Services.AddScoped(); // // builder.Services.AddScoped(); builder.Services.AddEndpointsApiExplorer(); // 스웨거 설정 추가 부분 // builder.Services.AddSwaggerGen(); builder.Services.AddCustomSwagger(); // SignalR 설정 추가 부분 builder.Services.AddSignalR(); builder.Services.AddCors(option => { option.AddPolicy("CorsPolicy", builder => { builder .WithOrigins("https://devacamate.ipstein.myds.me", "https://acamate.ipstein.myds.me") // 특정 도메인만 허용 .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); // 로그 설정 부분 builder.Logging.ClearProviders(); builder.Logging.AddConsole(); if (builder.Environment.IsDevelopment()) { builder.Logging.SetMinimumLevel(LogLevel.Trace); } else { builder.Logging.SetMinimumLevel(LogLevel.Warning); } //헤더 부분 builder.Services.AddScoped(); // 로컬 테스트 위한 부분 (올릴때는 꺼두기) builder.WebHost.UseUrls("http://0.0.0.0:5144"); ///// ===== builder 설정 부 ===== ///// var app = builder.Build(); if (app.Environment.IsDevelopment()) { // app.UseSwagger(); // app.UseSwaggerUI(); app.UseCustomSwaggerUI(); app.UseDeveloperExceptionPage(); // 좀더 자세한 예외 정보 제공 } else { app.UseExceptionHandler("/error"); app.UseHsts(); } // 로컬 테스트 위한 부분 (올릴떄는 켜두기) // app.UseHttpsRedirection(); // 헤더 미들웨어 부분 app.UseMiddleware("HEAD-CHECK"); // 이부분 봐야 합니다. // app.UseMiddleware("X-MyHeader"); app.UseRouting(); // app.MapControllers(); app.UseCors("CorsPolicy"); app.UseAuthorization(); app.UseWebSockets(); app.UseEndpoints(end => { end.MapControllers(); end.MapHub("/chatHub"); }); app.Run();