DependencyInjection.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using SharedKernel;
  2. using SharedKernel.Storage;
  3. using Application.Abstractions.Authentication;
  4. using Application.Abstractions.Data;
  5. using Application.Abstractions.Identity;
  6. using Application.Abstractions.Messaging.Email;
  7. using Infrastructure.Authentication;
  8. using Infrastructure.Messaging.Email;
  9. using Infrastructure.Persistence;
  10. using Infrastructure.Persistence.Identity;
  11. using Infrastructure.Storage;
  12. using Microsoft.AspNetCore.Authentication.JwtBearer;
  13. using Microsoft.AspNetCore.DataProtection;
  14. using Microsoft.AspNetCore.Identity;
  15. using Microsoft.AspNetCore.Identity.UI.Services;
  16. using Microsoft.EntityFrameworkCore;
  17. using Microsoft.Extensions.Configuration;
  18. using Microsoft.Extensions.DependencyInjection;
  19. using Microsoft.IdentityModel.Tokens;
  20. using System.Text;
  21. using StackExchange.Redis;
  22. namespace Infrastructure
  23. {
  24. public static class DependencyInjection
  25. {
  26. // SQL Server
  27. private static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration)
  28. {
  29. var dbConn = configuration.GetConnectionString("DefaultConnection");
  30. if (string.IsNullOrWhiteSpace(dbConn))
  31. {
  32. throw new InvalidOperationException("Connection string 'DefaultConnection' is not configured.");
  33. }
  34. services.AddDbContext<AppDbContext>(options => options.UseSqlServer(dbConn));
  35. services.AddDbContext<IdentityDbContext>(options => options.UseSqlServer(dbConn));
  36. services.AddScoped<IAppDbContext>(sp => sp.GetRequiredService<AppDbContext>());
  37. return services;
  38. }
  39. // Redis Server
  40. public static IServiceCollection AddRedis(this IServiceCollection services, IConfiguration configuration)
  41. {
  42. var settings = configuration.Get<AppSettings>()!;
  43. var redis = ConnectionMultiplexer.Connect(settings.Redis.DefaultConnection);
  44. services.AddSingleton<IConnectionMultiplexer>(redis);
  45. services.AddDataProtection().SetApplicationName(settings.App.Name).PersistKeysToStackExchangeRedis(redis, settings.Redis.DataProtectionKey).SetDefaultKeyLifetime(settings.Redis.DefaultKeyLifetime); // 기본 90일 주기
  46. // Distributed Cache 설정
  47. services.AddStackExchangeRedisCache(options =>
  48. {
  49. options.Configuration = settings.Redis.DefaultConnection;
  50. options.InstanceName = settings.Redis.CachePrefix;
  51. });
  52. return services;
  53. }
  54. private static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
  55. {
  56. var settings = configuration.Get<AppSettings>()!;
  57. services.AddHealthChecks().AddSqlServer(settings.ConnectionStrings.DefaultConnection).AddRedis(settings.Redis.DefaultConnection);
  58. return services;
  59. }
  60. private static IServiceCollection AddServices(this IServiceCollection services)
  61. {
  62. services.AddSingleton<IJwtTokenProvider, JwtTokenProvider>();
  63. services.AddTransient<IMailService, MailService>();
  64. services.AddTransient<IEmailSender, IdentityEmailSender>();
  65. services.AddScoped<IFileStorage, LocalFileStorage>();
  66. services.AddScoped<IEditorImageService, EditorImageService>();
  67. services.AddScoped<IIdentityUserReader, IdentityUserReader>();
  68. services.AddScoped<IIdentityUserWriter, IdentityUserWriter>();
  69. services.AddScoped<IIdentityRoleReader, IdentityRoleReader>();
  70. services.AddScoped<IIdentityRoleWriter, IdentityRoleWriter>();
  71. return services;
  72. }
  73. /**
  74. * ========================================================================================================================================================================================================
  75. * ========================================================================================================================================================================================================
  76. */
  77. // Admin 전용
  78. public static IServiceCollection AddAdminInfrastructure(this IServiceCollection services, IConfiguration configuration)
  79. {
  80. return services.AddDatabase(configuration).AddRedis(configuration).AddServices().AddHealthChecks(configuration);
  81. }
  82. /**
  83. * ========================================================================================================================================================================================================
  84. * ========================================================================================================================================================================================================
  85. */
  86. // API 전용
  87. public static IServiceCollection AddApiInfrastructure(this IServiceCollection services, IConfiguration configuration)
  88. {
  89. return services.AddDatabase(configuration).AddRedis(configuration).AddApiAuthentication(configuration).AddServices().AddHealthChecks(configuration);
  90. }
  91. private static IServiceCollection AddApiAuthentication(this IServiceCollection services, IConfiguration configuration)
  92. {
  93. var settings = configuration.Get<AppSettings>()!;
  94. // 인증 정책- JWT Bearer
  95. services.AddAuthentication(options =>
  96. {
  97. options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  98. options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  99. })
  100. .AddJwtBearer(options =>
  101. {
  102. options.RequireHttpsMetadata = false;
  103. options.TokenValidationParameters = new TokenValidationParameters
  104. {
  105. ValidateIssuer = true,
  106. ValidateAudience = true,
  107. ValidateLifetime = true,
  108. ValidateIssuerSigningKey = true,
  109. ValidIssuer = settings.JWT.Issuer,
  110. ValidAudience = settings.JWT.Audience,
  111. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.JWT.SecretKey)),
  112. ClockSkew = TimeSpan.Zero
  113. };
  114. });
  115. services.AddAuthorization();
  116. // Identity Core (Admin Handler의 UserManager/RoleManager 의존 해소용)
  117. services.AddIdentityCore<ApplicationUser>().AddRoles<IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>();
  118. return services;
  119. }
  120. }
  121. }