[성현모] DBProvider추가. LoginContext 변경

This commit is contained in:
SHM
2025-07-17 11:54:42 +09:00
parent 7a12be392a
commit 3c5f27ce68
22 changed files with 265 additions and 323 deletions

View File

@ -1,6 +0,0 @@
@AuthApi_HostAddress = http://localhost:5177
GET {{AuthApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -1,4 +1,5 @@
using AuthApi.Services;
using Azure.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
@ -6,15 +7,17 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using SystemX.Core;
using SystemX.Core.Controller;
using SystemX.Core.Model.Auth;
using WebApi.Library.Config;
namespace AuthApi.Controllers
{
[Tags("Auth")]
[Route("api/auth")]
[ApiController]
[ApiExplorerSettings(IgnoreApi = true)]
public class AuthController : CommonController
[ApiExplorerSettings(IgnoreApi = false)]
public class AuthController : CommonController<WebApiConfig>
{
private readonly AuthService _authService;
@ -25,36 +28,39 @@ namespace AuthApi.Controllers
_authService = authService;
}
[HttpGet("/health")]
[HttpGet("health")]
public async Task<IResult> Health()
{
Log4net.WriteLine($"[{GetRequestMethod()}:{GetMethodName()}] [Client IP:{GetClientIP()}] [RequestUrl:{GetRequestUrl()}]{Environment.NewLine}", LogType.CONTROLLER);
await Task.CompletedTask;
return Results.Ok("Healthy");
}
[HttpPost("regisger")]
public async Task<IResult> Register([FromBody] RegisterModel request)
public async Task<IResult> Register([FromBody] Register request)
{
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER);
Guid guid = Guid.NewGuid();
RegisterResponseModel response = new RegisterResponseModel();
Log4net.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
RegisterResponse response = new RegisterResponse();
if (request?.UserID != null && request?.Password != null)
{
response = await _authService.CreateUser(request);
}
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER);
Log4net.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response);
}
[HttpPost("login")]
public async Task<IResult> Login([FromBody] LoginModel request)
public async Task<IResult> Login([FromBody] Login request)
{
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER);
Log4net.WriteLine($"[Request]({guid}) api/auth/register{Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
LoginResponseModel response = new LoginResponseModel();
LoginResponse response = new LoginResponse();
response.UserID = request.UserID;
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
@ -75,20 +81,20 @@ namespace AuthApi.Controllers
await _authService.UpdateLoginInfo(request, response.RefreshToken);
}
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER);
Log4net.WriteLine($"[Response]({guid}) api/auth/register{Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response);
}
[HttpPost("logout")]
public async Task<IResult> Logout([FromBody] LogoutModel request)
public async Task<IResult> Logout([FromBody] Logout request)
{
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER);
Log4net.WriteLine($"[Request]({guid}) api/auth/register{Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
var response = _authService.LogoutUser(request);
await Task.CompletedTask;
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER);
Log4net.WriteLine($"[Response]({guid}) api/auth/register{Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response);
}
@ -113,7 +119,7 @@ namespace AuthApi.Controllers
};
}
private string GenerateJwtToken(LoginResponseModel loginResponseModel, bool isRefreshToken = false)
private string GenerateJwtToken(LoginResponse loginResponseModel, bool isRefreshToken = false)
{
var claims = new[]
{

View File

@ -1,59 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using System.Runtime.CompilerServices;
using SystemX.Core.Services;
using WebApi.Library.Config;
namespace AuthApi.Controllers
{
public class CommonController : ControllerBase
{
public readonly IServiceProvider _serviceProvider;
public readonly IHttpContextAccessor _httpContextAccessor;
public readonly ConfigService<WebApiConfig>? _configService;
protected static Guid guid { get; private set; } = Guid.NewGuid();
public CommonController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor)
{
//provider
_serviceProvider = serviceProvider;
_httpContextAccessor = httpContextAccessor;
//service
_configService = _serviceProvider.GetService<ConfigService<WebApiConfig>>();
}
/// <summary>
/// Request 클라이언트 IP
/// </summary>
protected virtual string? GetClientIP()
{
return _httpContextAccessor?.HttpContext?.Connection?.RemoteIpAddress?.ToString();
}
/// <summary>
/// Request 클라이언트 Url
/// </summary>
protected virtual string? GetRequestUrl()
{
return _httpContextAccessor?.HttpContext?.Request?.Path;
}
/// <summary>
/// Request 클라이언트 method: [GET] or [POST]
/// </summary>
protected virtual string? GetRequestMethod()
{
return _httpContextAccessor?.HttpContext?.Request?.Method;
}
/// <summary>
/// 현재 Action(함수) 이름 가져오기
/// </summary>
protected virtual string GetMethodName([CallerMemberName] string callerMemberName = "")
{
return callerMemberName;
}
}
}

View File

@ -1,10 +1,14 @@
using AuthApi.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.IdentityModel.Tokens;
using System;
using System.ComponentModel;
using System.Text;
using SystemX.Core.Services;
using WebApi.Library.Config;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Context;
string configDir = @"../../Config";
string configFileName = "WebApi.AuthApi.Config.json";
@ -26,14 +30,18 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
//singleton
builder.Services.AddSingleton<ConfigService<WebApiConfig>>();
builder.Services.AddScoped<AuthService>();
//scoped
builder.Services.AddScoped<AuthService>();
//db
builder.Services.AddSingleton<DbContextProvider>(); // Generic <20><><EFBFBD><EFBFBD>
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpContextAccessor();
//config preload, auth set
ConfigService<WebApiConfig> preloadConfig = new ConfigService<WebApiConfig>();
@ -61,7 +69,7 @@ if (preloadConfig.OpenConfig($@"{configDir}/{configFileName}") == true)
ValidAudience = $"{config?.Auth?.audience}",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{config?.Auth?.accessTokenSecret}"))
};
});
});
}
else
{
@ -84,6 +92,24 @@ if (configService?.OpenConfig($@"{configDir}/{configFileName}") == true)
{
serverUrl = $"{apiConfig?.Server?.Address}:{apiConfig?.Server?.Port}";
isIIS = apiConfig!.Server.IIS;
using(var scoped = app.Services.CreateScope())
{
var dbProvider = scoped.ServiceProvider.GetRequiredService<DbContextProvider>();
dbProvider?.SetDBList(apiConfig?.DataBase);
}
//dbcontext set
//app.Use(async (context, next) =>
//{
// var dbProvider = context.RequestServices.GetService<DbContextProvider>();
// // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// dbProvider?.SetDBList(apiConfig?.DataBase);
// await next.Invoke();
//});
//var dbProviderService = app.Services.GetService<DbContextProvider>();
//dbProviderService?.SetDBList(apiConfig?.DataBase);
}
}
else

View File

@ -6,8 +6,8 @@ using SystemX.Core.Config.Model;
using System.Data;
using SystemX.Core.DB;
using Microsoft.EntityFrameworkCore;
using SystemX.Core.DB.DBContext.AccountDB.Context;
using SystemX.Core.DB.DBContext.AccountDB.Tables;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Context;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Tables;
namespace AuthApi.Services
{
@ -16,26 +16,22 @@ namespace AuthApi.Services
private readonly IServiceProvider _serviceProvider;
private readonly IServiceScopeFactory _scopeFactory;
private readonly ConfigService<WebApiConfig>? _configService;
private readonly DataBase? _accountDB;
private static List<LoginResponseModel> Session = new List<LoginResponseModel>();
private static List<LoginResponse> Session = new List<LoginResponse>();
public AuthService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService<WebApiConfig> configSerice)
{
_serviceProvider = serviceProvider;
_configService = configSerice;
_scopeFactory = scopeFactory;
_accountDB = _configService?.GetConfig()?.DataBase?.Find(x => x.DBContext == "VpkiAccountDbContext");
}
/// <summary>
/// create new user
/// </summary>
public async Task<RegisterResponseModel> CreateUser(RegisterModel registerModel)
{
//response
RegisterResponseModel response = new RegisterResponseModel();
public async Task<RegisterResponse> CreateUser(Register registerModel)
{
RegisterResponse response = new RegisterResponse();
response.EC = ERROR_CODE.EC_USER_REGISTER_FAILED;
response.UserID = registerModel.UserID;
response.Role = registerModel.Role;
@ -44,39 +40,42 @@ namespace AuthApi.Services
//context
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>();
if (context is not null)
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync();
if (user?.Count <= 0)
if (context is not null)
{
string auid = Guid.NewGuid().ToString();
//user
TUser newUser = new TUser
var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync();
if (user?.Count <= 0)
{
CAuid = auid,
CUserId = registerModel.UserID,
CPasswordHashed = registerModel.Password,
CCreateDateTime = DateTime.Now,
CLastLoginDateTime = new DateTime()
};
//role
TRole newUserRole = new TRole
{
CAuid = auid,
CRoleId = Convert.ToByte(registerModel.Role),
CRoleName = registerModel.Role.ToString()
};
using (var transaction = await context.CreateTransactionAsync())
{
await context.AddAsync(newUser);
await context.AddAsync(newUserRole);
var result = await context.CloseTransactionAsync(transaction);
if (result == true)
string auid = Guid.NewGuid().ToString();
//user
TUser newUser = new TUser
{
response.EC = ERROR_CODE.EC_OK;
CAuid = auid,
CUserId = registerModel.UserID,
CPasswordHashed = registerModel.Password,
CCreateDateTime = DateTime.Now,
CLastLoginDateTime = new DateTime()
};
//role
TRole newUserRole = new TRole
{
CAuid = auid,
CRoleId = Convert.ToByte(registerModel.Role),
CRoleName = registerModel.Role.ToString()
};
using (var transaction = await context.CreateTransactionAsync())
{
await context.AddAsync(newUser);
await context.AddAsync(newUserRole);
var result = await context.CloseTransactionAsync(transaction);
if (result == true)
{
response.EC = ERROR_CODE.EC_OK;
}
}
}
}
@ -89,80 +88,82 @@ namespace AuthApi.Services
/// <summary>
/// select user(login)
/// </summary>
public async Task<LoginResponseModel> SelectUser(LoginModel loginModel)
public async Task<LoginResponse> SelectUser(Login loginModel)
{
//response
LoginResponseModel response = new LoginResponseModel();
LoginResponse response = new LoginResponse();
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
response.UserID = loginModel.UserID;
//var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower());
//if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime())
//{
// Session.Remove(session);
//}
var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower());
if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime())
{
Session.Remove(session);
}
//기존 로그인 체크
// if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false)
if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false)
{
if (loginModel != null)
{
//context
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>();
if (context is not null)
{
try
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
if (context is not null)
{
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
try
{
//select user
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
{
if (selectUser.CPasswordHashed == loginModel?.Password)
//select user
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{
//select role
var selectRole = await context.TRoles.FindAsync(selectUser.CAuid);
if (selectRole != null)
if (selectUser.CPasswordHashed == loginModel?.Password)
{
response.Role = (UserRole)Enum.Parse(typeof(UserRole), selectRole.CRoleId.ToString());
response.RoleName = selectRole.CRoleName;
}
//select role
var selectRole = await context.TRoles.FindAsync(selectUser.CAuid);
if (selectRole != null)
{
response.Role = (UserRole)Enum.Parse(typeof(UserRole), selectRole.CRoleId.ToString());
response.RoleName = selectRole.CRoleName;
}
// Session.Add(response);
if (selectUser.CState == (byte)UserState.Active)
{
response.EC = ERROR_CODE.EC_OK;
Session.Add(response);
if (selectUser.CState == (byte)UserState.Active)
{
response.EC = ERROR_CODE.EC_OK;
}
else if (selectUser.CState == (byte)UserState.Inactive)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_INAVTIVE;
}
else if (selectUser.CState == (byte)UserState.Block)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_BLOCKED;
}
}
else if (selectUser.CState == (byte)UserState.Inactive)
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_INAVTIVE;
}
else if (selectUser.CState == (byte)UserState.Block)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_BLOCKED;
response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD;
}
}
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD;
response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
Log4net.WriteLine($"{response.EC}", LogType.Error);
}
await context.CloseTransactionAsync(transaction);
}
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
Log4net.WriteLine($"{response.EC}", LogType.Error);
}
await context.CloseTransactionAsync(transaction);
}
}
catch (Exception e)
{
Log4net.WriteLine($"Select User Transaction Error", LogType.Exception);
Log4net.WriteLine(e);
catch (Exception e)
{
Log4net.WriteLine($"Select User Transaction Error", LogType.Exception);
Log4net.WriteLine(e);
}
}
}
}
@ -172,71 +173,74 @@ namespace AuthApi.Services
return response;
}
public async Task<bool> UpdateLoginInfo(LoginModel loginModel, string? RefreshToken = "")
public async Task<bool> UpdateLoginInfo(Login loginModel, string? RefreshToken = "")
{
bool result = false;
bool transactionResult = true;
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>();
if (context is not null)
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
if (context is not null)
{
using (var transaction = await context.CreateTransactionAsync())
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{
try
using (var transaction = await context.CreateTransactionAsync())
{
//user info
selectUser.CLastLoginDateTime = DateTime.Now;
context.Update(selectUser);
//refresh token
var findRefreshToken = await context.TRefreshTokens.AsNoTracking().FirstOrDefaultAsync(x => x.CAuid == selectUser.CAuid);
//null이면(없으면) add
if (findRefreshToken == null)
try
{
await context.AddAsync(new TRefreshToken
//user info
selectUser.CLastLoginDateTime = DateTime.Now;
context.Update(selectUser);
//refresh token
var findRefreshToken = await context.TRefreshTokens.AsNoTracking().FirstOrDefaultAsync(x => x.CAuid == selectUser.CAuid);
//null이면(없으면) add
if (findRefreshToken == null)
{
CAuid = selectUser.CAuid,
CRefreshToken = $"{RefreshToken}"
});
await context.AddAsync(new TRefreshToken
{
CAuid = selectUser.CAuid,
CRefreshToken = $"{RefreshToken}"
});
}
//있으면 update
else
{
findRefreshToken.CRefreshToken = $"{RefreshToken}";
context.Update(findRefreshToken);
}
//commit
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
result = true;
}
//있으면 update
else
catch (Exception ex)
{
findRefreshToken.CRefreshToken = $"{RefreshToken}";
context.Update(findRefreshToken);
Log4net.WriteLine(ex);
}
//commit
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
result = true;
transactionResult = await context.CloseTransactionAsync(transaction);
}
catch (Exception ex)
{
Log4net.WriteLine(ex);
}
transactionResult = await context.CloseTransactionAsync(transaction);
}
}
else
{
Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error);
}
else
{
Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error);
}
//db error
if (transactionResult == false)
{
Log4net.WriteLine($"Transaction Error", LogType.Error);
}
else
{
Log4net.WriteLine($"Transaction Success", LogType.DB);
//db error
if (transactionResult == false)
{
Log4net.WriteLine($"Transaction Error", LogType.Error);
}
else
{
Log4net.WriteLine($"Transaction Success", LogType.DB);
}
}
}
}
@ -244,9 +248,9 @@ namespace AuthApi.Services
return result;
}
public LogoutResponseModel LogoutUser(LogoutModel logoutModel)
public LogoutResponse LogoutUser(Logout logoutModel)
{
LogoutResponseModel response = new LogoutResponseModel();
LogoutResponse response = new LogoutResponse();
response.UserID = logoutModel.UserID;
response.EC = ERROR_CODE.EC_USER_LOGOUT_FAILED;
@ -259,5 +263,11 @@ namespace AuthApi.Services
return response;
}
private AccountDbContext? GetAccountDBContext(DbContextProvider provider, int dbID)
{
var connectionString = _configService?.GetConfig()?.DataBase?.Find(x => x.DBID == dbID);
return provider?.GetDBContext<AccountDbContext>($"{connectionString?.DBName}");
}
}
}