From 9f6a5b882ce6614ef96e52a7fcd0512b96f83424 Mon Sep 17 00:00:00 2001 From: SEAN-59 Date: Mon, 16 Jun 2025 17:44:42 +0900 Subject: [PATCH] =?UTF-8?q?[=E2=9C=A8]=20=EC=9A=B4=EC=98=81=EC=B2=B4?= =?UTF-8?q?=EC=A0=9C=EB=B3=84=20=EB=8F=99=EC=9E=91=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 운영체제가 다르다고 다른 API 나 다른 로직을 타는게 아닌 하나의 로직으로 돌게 만들기 위해서 로직 수정 --- Document/Rule.md | 26 ++++ Program.cs | 6 +- Program/Common/Auth/DedicateWeb.cs | 76 ++++++++++ Program/Common/Data/SessionManager.cs | 53 +++++++ Program/Controllers/V1/AppController.cs | 11 +- Program/Controllers/V1/OutController.cs | 19 +-- Program/Controllers/V1/SessionController.cs | 37 +++++ Program/Controllers/V1/UserController.cs | 62 ++++---- .../Services/V1/Interfaces/ISessionService.cs | 7 +- .../Services/V1/Interfaces/IUserService.cs | 1 - Program/Services/V1/SessionService.cs | 139 +++++++++++++----- Program/Services/V1/UserService.cs | 98 ++---------- 12 files changed, 356 insertions(+), 179 deletions(-) create mode 100644 Document/Rule.md create mode 100644 Program/Common/Auth/DedicateWeb.cs create mode 100644 Program/Common/Data/SessionManager.cs create mode 100644 Program/Controllers/V1/SessionController.cs diff --git a/Document/Rule.md b/Document/Rule.md new file mode 100644 index 0000000..6c1b12f --- /dev/null +++ b/Document/Rule.md @@ -0,0 +1,26 @@ +# AcaMate API 문서 + +## 개요 + +## 프로젝트 구조 +### 각 폴더 간 관계 +#### 역할 +- Controller: API 요청을 처리하고 응답을 반환하는 역할 +- Service: 비즈니스 로직을 처리하는 역할 +- Repository: 데이터베이스와의 상호작용을 처리하는 역할 +- Model: 데이터 구조를 정의하는 역할 +#### 폴더 관계 +- Controller 는 Service 를 참조하고, Service 는 Repository 를 참조한다. +- Controller 는 Service 와 1:N 관계를 가진다. +- Service 는 Repository 와 1:N 관계를 가진다. +- Controller에서 Repository를 직접 참조하지 않는다. +- Repository 와 Service 는 모두 Interface 를 통해 의존성을 주입받는다. +- Common 폴더는 모든 계층에서 공통적으로 사용되는 유틸리티나 헬퍼 클래스를 포함한다. + + +### 오류 코드 +- 0xx : 성공 +- 1xx : 입력 오류 +- 2xx : 출력 오류 +- 3xx : 통신 오류 +- 999 : 알 수 없는 오류 \ No newline at end of file diff --git a/Program.cs b/Program.cs index 91e937d..2a42e29 100644 --- a/Program.cs +++ b/Program.cs @@ -26,7 +26,7 @@ using Back.Program.Services.V1.Interfaces; Boolean isLocal = false; // 로컬 테스트 할 때는 이거 키고 아니면 끄기 -// isLocal = true; +isLocal = true; var builder = WebApplication.CreateBuilder(args); @@ -117,7 +117,9 @@ builder.Services.AddSingleton(); builder.Services.AddHostedService(); // PUSH 설정부 끝 + builder.Services.AddControllers(); + // 세션 설정 // IN-MEMORY 캐시 builder.Services.AddDistributedMemoryCache(); @@ -140,6 +142,8 @@ builder.Services.AddScoped(); // builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); // builder.Services.AddScoped(); // // builder.Services.AddScoped(); diff --git a/Program/Common/Auth/DedicateWeb.cs b/Program/Common/Auth/DedicateWeb.cs new file mode 100644 index 0000000..5f2c03e --- /dev/null +++ b/Program/Common/Auth/DedicateWeb.cs @@ -0,0 +1,76 @@ +using System.Security.Claims; +using System.Text.Json; +using Back.Program.Common.Data; +using Back.Program.Common.Model; +using Back.Program.Services.V1.Interfaces; + +namespace Back.Program.Common.Auth; + +public class DedicateWeb( + ILogger _logger, + SessionManager _sessionManager, + IRepositoryService _repositoryService, + JwtTokenService _jwtTokenService, + IAppService _appService) +{ + public async Task<(string code, string result)> GetAuthToken() + { + var summary = "GetAuthToken"; + try + { + // 1. 세션에서 토큰 가져오기 + var (result, token) = await _sessionManager.GetString("token"); + _logger.LogInformation($"세션에서 토큰 가져오기 결과: {result}, 토큰: {token}"); + + if (!result || string.IsNullOrEmpty(token)) + { + _logger.LogWarning($"세션에 토큰이 없습니다"); + return ("200", "세션에 토큰 없음"); + } + + // 2. 토큰 검증 + var validToken = await _jwtTokenService.ValidateToken(token); + _logger.LogInformation($"토큰 검증 결과: {validToken != null}"); + + if (validToken == null) + { + // 3. 토큰이 유효하지 않으면 리프레시 토큰으로 새 토큰 발급 시도 + var (refreshResult, refreshToken) = await _sessionManager.GetString("refresh"); + _logger.LogInformation($"리프레시 토큰 가져오기 결과: {refreshResult}, 토큰: {refreshToken}"); + + if (!refreshResult || string.IsNullOrEmpty(refreshToken)) + { + _logger.LogWarning($"리프레시 토큰이 없습니다"); + return ("200", "리프레시 토큰 없음"); + } + + // 4. 리프레시 토큰으로 새 토큰 발급 + var retryResult = await _appService.RetryAccess(summary, refreshToken); + _logger.LogInformation($"토큰 재발급 결과: {retryResult.status.code}"); + + if (retryResult.status.code == "000") + { + // 5. 새 토큰을 세션에 저장 + var data = JsonSerializer.Deserialize(JsonSerializer.Serialize(retryResult.data)); + var newToken = data.GetProperty("access").GetString(); + await _sessionManager.SetString("token", newToken); + _logger.LogInformation($"[{summary}] 새 토큰 세션 저장 완료"); + + return ("000", newToken); + } + else + { + _logger.LogWarning($"[{summary}] 토큰 갱신 실패: {retryResult.status.message}"); + return ("102", "토큰 갱신 실패"); + } + } + return ("000", token); + } + catch (Exception ex) + { + _logger.LogError($"[{summary}] 세션 데이터 조회 중 오류: {ex.Message}"); + _logger.LogError($"[{summary}] 스택 트레이스: {ex.StackTrace}"); + return ("100", "세션 데이터 조회 중 오류"); + } + } +} \ No newline at end of file diff --git a/Program/Common/Data/SessionManager.cs b/Program/Common/Data/SessionManager.cs new file mode 100644 index 0000000..6ff090f --- /dev/null +++ b/Program/Common/Data/SessionManager.cs @@ -0,0 +1,53 @@ +namespace Back.Program.Common.Data; + +public class SessionManager +{ + private readonly IHttpContextAccessor _http; + + public SessionManager(IHttpContextAccessor http) + { + _http = http; + } + + public Task SetString(string key, string value) + { + try + { + _http.HttpContext.Session.SetString(key, value); + return Task.FromResult(true); + } + catch + { + return Task.FromResult(false); + } + } + public Task<(bool result, string data)> GetString(string key) + { + try + { + var value = _http.HttpContext.Session.GetString(key); + return Task.FromResult((true, value ?? string.Empty)); + } + catch + { + return Task.FromResult((false, "")); + } + } + public Task Remove(string key) + { + try + { + _http.HttpContext.Session.Remove(key); + return Task.FromResult(true); + } + catch + { + return Task.FromResult(false); + } + } + + + + + +} \ No newline at end of file diff --git a/Program/Controllers/V1/AppController.cs b/Program/Controllers/V1/AppController.cs index 2760112..2e4d6b1 100644 --- a/Program/Controllers/V1/AppController.cs +++ b/Program/Controllers/V1/AppController.cs @@ -25,9 +25,10 @@ namespace Back.Program.Controllers.V1 private readonly JwtTokenService _jwtTokenService; private readonly IAppService _appService; private readonly IAppRepository _appRepository; - private readonly ISessionService _sessionService; + private readonly SessionManager _sessionManager; - public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService, IAppService appService, IAppRepository appRepository, ISessionService sessionService) + public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, + JwtTokenService jwtTokenService, IAppService appService, IAppRepository appRepository, SessionManager sessionManager) { _dbContext = dbContext; _logger = logger; @@ -35,7 +36,7 @@ namespace Back.Program.Controllers.V1 _jwtTokenService = jwtTokenService; _appService = appService; _appRepository = appRepository; - _sessionService = sessionService; + _sessionManager = sessionManager; } @@ -82,7 +83,7 @@ namespace Back.Program.Controllers.V1 return BadRequest(APIResponse.InvalidInputError()); } - var (success, value) = await _sessionService.GetString(key); + var (success, value) = await _sessionManager.GetString(key); if (!success) { return BadRequest(APIResponse.InvalidInputError()); @@ -106,7 +107,7 @@ namespace Back.Program.Controllers.V1 foreach(var request in requests) { Console.WriteLine($"세션 저장 시도 - key: {request.key}, value: {request.value}"); - var success = await _sessionService.SetString(request.key, request.value); + var success = await _sessionManager.SetString(request.key, request.value); if (!success) { Console.WriteLine($"세션 저장 실패 - key: {request.key}"); diff --git a/Program/Controllers/V1/OutController.cs b/Program/Controllers/V1/OutController.cs index eebdfc5..10e3e64 100644 --- a/Program/Controllers/V1/OutController.cs +++ b/Program/Controllers/V1/OutController.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using Back.Program.Common.Data; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; @@ -21,16 +22,16 @@ public class OutController: ControllerBase private readonly IRepositoryService _repositoryService; private readonly IUserService _userService; private readonly IKakaoService _kakaoService; - private readonly ISessionService _sessionService; + private readonly SessionManager _sessionManager; public OutController(ILogger logger, - IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService, ISessionService sessionService) + IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService, SessionManager sessionManager) { _logger = logger; _repositoryService = repositoryService; _userService = userService; _kakaoService = kakaoService; - _sessionService = sessionService; + _sessionManager = sessionManager; } [HttpGet("kakao/auth")] @@ -39,7 +40,7 @@ public class OutController: ControllerBase { if (!string.IsNullOrEmpty(redirectPath)) { - await _sessionService.SetString("redirectPath", redirectPath); + await _sessionManager.SetString("redirectPath", redirectPath); } var url = await _kakaoService.GetAuthorizationUrl(scope ?? ""); @@ -81,12 +82,12 @@ public class OutController: ControllerBase string refresh = data.refresh; _logger.LogInformation($"토큰 저장 시도 - token: {token}, refresh: {refresh}"); - if (await _sessionService.SetString("token", token) && - await _sessionService.SetString("refresh", refresh)) + if (await _sessionManager.SetString("token", token) && + await _sessionManager.SetString("refresh", refresh)) { _logger.LogInformation("세션 저장 성공"); - var (hasPath, redirectPath) = await _sessionService.GetString("redirectPath"); - await _sessionService.Remove("redirectPath"); // 사용 후 세션에서 제거 + var (hasPath, redirectPath) = await _sessionManager.GetString("redirectPath"); + await _sessionManager.Remove("redirectPath"); // 사용 후 세션에서 제거 var redirectUrl = hasPath && !string.IsNullOrEmpty(redirectPath) ? $"{redirectPath}?auth=true" @@ -107,7 +108,7 @@ public class OutController: ControllerBase else if (loginResult.status.code == "001") { _logger.LogInformation("회원가입 필요"); - if (await _sessionService.SetString("snsId", snsId)) + if (await _sessionManager.SetString("snsId", snsId)) { return Redirect("/auth/register"); } diff --git a/Program/Controllers/V1/SessionController.cs b/Program/Controllers/V1/SessionController.cs new file mode 100644 index 0000000..11bef2c --- /dev/null +++ b/Program/Controllers/V1/SessionController.cs @@ -0,0 +1,37 @@ +using Back.Program.Common.Data; +using Back.Program.Services.V1.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace Back.Program.Controllers.V1; + +/// +/// USER는 사용자가 자신의 데이터를 보거나 만들거나 하는 등 직접 사용하는 경우에 사용 +/// +[ApiController] +[Route("/api/v1/in/user")] +[ApiExplorerSettings(GroupName = "")] +public class SessionController : ControllerBase +{ + + private readonly ILogger _logger; + private readonly IRepositoryService _repositoryService; + private readonly SessionManager _sessionManager; + private readonly ISessionService _sessionService; + + private SessionController(ILogger logger, + IRepositoryService repositoryService, SessionManager sessionManager, ISessionService sessionService) + { + _logger = logger; + _repositoryService = repositoryService; + _sessionManager = sessionManager; + _sessionService = sessionService; + } + [HttpGet("session/user")] + [CustomOperation("세션 정보 확인", "세션 정보 확인", "사용자")] + public async Task GetSessionData() + { + string summary = _repositoryService.ReadSummary(typeof(UserController), "GetSessionData"); + var result = await _sessionService.GetSessionData(summary); + return Ok(result); + } +} \ No newline at end of file diff --git a/Program/Controllers/V1/UserController.cs b/Program/Controllers/V1/UserController.cs index 18fc255..aa993e1 100644 --- a/Program/Controllers/V1/UserController.cs +++ b/Program/Controllers/V1/UserController.cs @@ -17,29 +17,32 @@ namespace Back.Program.Controllers.V1 [ApiController] [Route("/api/v1/in/user")] [ApiExplorerSettings(GroupName = "사용자")] - public class UserController : ControllerBase + public class UserController( + ILogger logger, + SessionManager sessionManager, + DedicateWeb dedicateWeb, + IRepositoryService repositoryService, + IUserService userService) + : ControllerBase { - private readonly ILogger _logger; - private readonly IRepositoryService _repositoryService; - private readonly IUserService _userService; + private readonly ILogger _logger = logger; + private readonly SessionManager _sessionManager = sessionManager; - public UserController(ILogger logger, - IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService) - { - _logger = logger; - _repositoryService = repositoryService; - _userService = userService; - } - [HttpGet] [CustomOperation("회원 정보 조회", "회원 정보 조회 (자기자신)", "사용자")] public async Task GetUserData(string token) { if (string.IsNullOrEmpty(token)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "GetUserData"); + string summary = repositoryService.ReadSummary(typeof(UserController), "GetUserData"); + if (token == "VO00") + { + var (code, WebAuthResult) = await dedicateWeb.GetAuthToken(); + if (code != "000") return Ok(APIResponse.Send(code, $"{WebAuthResult}", new { })); + token = WebAuthResult; + } - var result = await _userService.GetUser(summary, token); + var result = await userService.GetUser(summary, token); return Ok(result); } @@ -52,8 +55,8 @@ namespace Back.Program.Controllers.V1 if (string.IsNullOrEmpty(accType) && string.IsNullOrEmpty(snsId)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "Login"); - var result = await _userService.Login(summary, accType, snsId); + string summary = repositoryService.ReadSummary(typeof(UserController), "Login"); + var result = await userService.Login(summary, accType, snsId); return Ok(result); } @@ -63,9 +66,9 @@ namespace Back.Program.Controllers.V1 public async Task UserRegister([FromBody] UserAll request) { if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "UserRegister"); + string summary = repositoryService.ReadSummary(typeof(UserController), "UserRegister"); - var result = await _userService.Register(summary, request); + var result = await userService.Register(summary, request); return Ok(result); } @@ -75,9 +78,9 @@ namespace Back.Program.Controllers.V1 { if (string.IsNullOrEmpty(token)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "Logout"); + string summary = repositoryService.ReadSummary(typeof(UserController), "Logout"); - var result = await _userService.Logout(summary, token); + var result = await userService.Logout(summary, token); return Ok(result); } @@ -88,8 +91,8 @@ namespace Back.Program.Controllers.V1 { if (string.IsNullOrEmpty(token)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "Cancel"); - var result = await _userService.Cancel(summary, token); + string summary = repositoryService.ReadSummary(typeof(UserController), "Cancel"); + var result = await userService.Cancel(summary, token); return Ok(result); } @@ -100,21 +103,12 @@ namespace Back.Program.Controllers.V1 { if (string.IsNullOrEmpty(token)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = _repositoryService.ReadSummary(typeof(UserController), "ReadAcademyInfo"); + string summary = repositoryService.ReadSummary(typeof(UserController), "ReadAcademyInfo"); - var result = await _userService.GetAcademy(summary, token); + var result = await userService.GetAcademy(summary, token); return Ok(result); } - - [HttpGet("auth/session")] - [CustomOperation("세션 정보 확인", "세션 정보 확인", "사용자")] - public async Task GetSessionData() - { - string summary = _repositoryService.ReadSummary(typeof(UserController), "GetSessionData"); - var result = await _userService.GetSessionData(summary); - return Ok(result); - } - + } } diff --git a/Program/Services/V1/Interfaces/ISessionService.cs b/Program/Services/V1/Interfaces/ISessionService.cs index b78b4ba..12fcdb0 100644 --- a/Program/Services/V1/Interfaces/ISessionService.cs +++ b/Program/Services/V1/Interfaces/ISessionService.cs @@ -1,8 +1,9 @@ +using Back.Program.Common.Model; +using Back.Program.Models.Entities; + namespace Back.Program.Services.V1.Interfaces; public interface ISessionService { - Task SetString(string key, string value); - Task<(bool result, string data)> GetString(string key); - Task Remove(string key); + Task> GetSessionData(string summary); } \ No newline at end of file diff --git a/Program/Services/V1/Interfaces/IUserService.cs b/Program/Services/V1/Interfaces/IUserService.cs index 68df934..7ebd2c6 100644 --- a/Program/Services/V1/Interfaces/IUserService.cs +++ b/Program/Services/V1/Interfaces/IUserService.cs @@ -11,6 +11,5 @@ namespace Back.Program.Services.V1.Interfaces Task> Logout(string summary, string token); Task> Cancel(string summary, string token); Task> GetAcademy(string summary, string token); - Task> GetSessionData(string summary); } } \ No newline at end of file diff --git a/Program/Services/V1/SessionService.cs b/Program/Services/V1/SessionService.cs index c876b2c..a36e561 100644 --- a/Program/Services/V1/SessionService.cs +++ b/Program/Services/V1/SessionService.cs @@ -1,50 +1,111 @@ +using System.Security.Claims; +using System.Text.Json; +using Back.Program.Common.Auth; +using Back.Program.Common.Data; +using Back.Program.Common.Model; +using Back.Program.Repositories.V1.Interfaces; using Back.Program.Services.V1.Interfaces; namespace Back.Program.Services.V1; public class SessionService: ISessionService { - private readonly IHttpContextAccessor _http; - public SessionService(IHttpContextAccessor http) + private readonly ILogger _logger; + private readonly IUserRepository _userRepository; + private readonly JwtTokenService _jwtTokenService; + private readonly IRepositoryService _repositoryService; + private readonly ILogRepository _logRepository; + private readonly SessionManager _sessionManager; + private readonly IAppService _appService; + + public SessionService(ILogger logger, IUserRepository userRepository, + JwtTokenService jwtTokenService, + IRepositoryService repositoryService, ILogRepository logRepository, + SessionManager sessionManager, IAppService appService) { - _http = http; + _logger = logger; + _userRepository = userRepository; + _jwtTokenService = jwtTokenService; + _repositoryService = repositoryService; + _logRepository = logRepository; + _sessionManager = sessionManager; + _appService = appService; } - public Task SetString(string key, string value) - { - try + public async Task> GetSessionData(string summary) { - _http.HttpContext.Session.SetString(key, value); - return Task.FromResult(true); + try + { + _logger.LogInformation($"[{summary}] 세션 데이터 조회 시작"); + + // 1. 세션에서 토큰 가져오기 + var (result, token) = await _sessionManager.GetString("token"); + _logger.LogInformation($"[{summary}] 세션에서 토큰 가져오기 결과: {result}, 토큰: {token}"); + + if (!result || string.IsNullOrEmpty(token)) + { + _logger.LogWarning($"[{summary}] 세션에 토큰이 없습니다"); + return APIResponse.Send("200", "세션에 토큰이 없습니다", new { }); + } + + // 2. 토큰 검증 + var validToken = await _jwtTokenService.ValidateToken(token); + _logger.LogInformation($"[{summary}] 토큰 검증 결과: {validToken != null}"); + + if (validToken == null) + { + // 3. 토큰이 유효하지 않으면 리프레시 토큰으로 새 토큰 발급 시도 + var (refreshResult, refreshToken) = await _sessionManager.GetString("refresh"); + _logger.LogInformation($"[{summary}] 리프레시 토큰 가져오기 결과: {refreshResult}, 토큰: {refreshToken}"); + + if (!refreshResult || string.IsNullOrEmpty(refreshToken)) + { + _logger.LogWarning($"[{summary}] 리프레시 토큰이 없습니다"); + return APIResponse.Send("201", "리프레시 토큰이 없습니다", new { }); + } + + // 4. 리프레시 토큰으로 새 토큰 발급 + var retryResult = await _appService.RetryAccess(summary, refreshToken); + _logger.LogInformation($"[{summary}] 토큰 재발급 결과: {retryResult.status.code}"); + + if (retryResult.status.code == "000") + { + // 5. 새 토큰을 세션에 저장 + var data = JsonSerializer.Deserialize(JsonSerializer.Serialize(retryResult.data)); + var newToken = data.GetProperty("access").GetString(); + await _sessionManager.SetString("token", newToken); + _logger.LogInformation($"[{summary}] 새 토큰 세션 저장 완료"); + + // 6. 새 토큰으로 사용자 정보 조회 + validToken = await _jwtTokenService.ValidateToken(newToken); + } + else + { + _logger.LogWarning($"[{summary}] 토큰 갱신 실패: {retryResult.status.message}"); + return APIResponse.Send("202", "토큰 갱신 실패", new { }); + } + } + + // 7. 최종적으로 유효한 토큰으로 사용자 정보 조회 + var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; + _logger.LogInformation($"[{summary}] 사용자 ID: {uid}"); + + var user = await _userRepository.FindUser(uid); + _logger.LogInformation($"[{summary}] 사용자 정보 조회 결과: {user != null}"); + + if (user == null) + { + _logger.LogWarning($"[{summary}] 사용자 정보를 찾을 수 없습니다"); + return APIResponse.Send("203", "사용자 정보를 찾을 수 없습니다", new { }); + } + + _logger.LogInformation($"[{summary}] 세션 데이터 조회 성공: {user.name}"); + return APIResponse.Send("000", $"[{summary}], 정상", user); + } + catch (Exception ex) + { + _logger.LogError($"[{summary}] 세션 데이터 조회 중 오류: {ex.Message}"); + _logger.LogError($"[{summary}] 스택 트레이스: {ex.StackTrace}"); + return APIResponse.InternalSeverError($"[{summary}], 세션 데이터 조회 실패"); + } } - catch - { - return Task.FromResult(false); - } - } - public Task<(bool result, string data)> GetString(string key) - { - try - { - var value = _http.HttpContext.Session.GetString(key); - return Task.FromResult((true, value ?? string.Empty)); - } - catch - { - return Task.FromResult((false, "")); - } - } - public Task Remove(string key) - { - try - { - _http.HttpContext.Session.Remove(key); - return Task.FromResult(true); - } - catch - { - return Task.FromResult(false); - } - } - - } \ No newline at end of file diff --git a/Program/Services/V1/UserService.cs b/Program/Services/V1/UserService.cs index 2fe71c7..deca333 100644 --- a/Program/Services/V1/UserService.cs +++ b/Program/Services/V1/UserService.cs @@ -5,6 +5,7 @@ using Back.Program.Models.Entities; using Back.Program.Repositories.V1.Interfaces; using Back.Program.Services.V1.Interfaces; using System.Text.Json; +using Back.Program.Common.Data; namespace Back.Program.Services.V1 { @@ -15,23 +16,24 @@ namespace Back.Program.Services.V1 private readonly JwtTokenService _jwtTokenService; private readonly IRepositoryService _repositoryService; private readonly ILogRepository _logRepository; - private readonly ISessionService _sessionService; private readonly IAppService _appService; + private readonly SessionManager _sessionManager; public UserService(ILogger logger, IUserRepository userRepository, JwtTokenService jwtTokenService, IRepositoryService repositoryService, ILogRepository logRepository, - ISessionService sessionService, IAppService appService) + IAppService appService, SessionManager sessionManager) { _logger = logger; _userRepository = userRepository; _jwtTokenService = jwtTokenService; _repositoryService = repositoryService; _logRepository = logRepository; - _sessionService = sessionService; _appService = appService; + _sessionManager = sessionManager; } + public async Task> GetUser(string summary, string token) { var validToken = await _jwtTokenService.ValidateToken(token); @@ -41,7 +43,7 @@ namespace Back.Program.Services.V1 var user = await _userRepository.FindUser(uid); return APIResponse.Send("000", $"[{summary}], 정상", user); - // user 없는 경우가 없네? 그거도 만들것 + // user 없는 경우가 없네? 그거도 만들것 } public async Task> Login(string summary, string accType, string snsId) @@ -52,7 +54,7 @@ namespace Back.Program.Services.V1 var user = await _userRepository.FindUser(login.uid); if (user == null) - return APIResponse.Send("002", $"[{summary}], 회원 정보 오류", new {}); + return APIResponse.Send("002", $"[{summary}], 회원 정보 오류", new { }); user.login_date = DateTime.Now; var token = _jwtTokenService.GenerateJwtToken(user.uid); @@ -176,7 +178,7 @@ namespace Back.Program.Services.V1 refresh.revoke_Date = DateTime.Now; if (await _repositoryService.SaveData(refresh)) { - return APIResponse.Send("000", $"[{summary}], 로그아웃 정상", new {}); + return APIResponse.Send("000", $"[{summary}], 로그아웃 정상", new { }); } } @@ -190,7 +192,7 @@ namespace Back.Program.Services.V1 var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var user = await _userRepository.FindUser(uid); - if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new {}); + if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new { }); if (await _repositoryService.DeleteData(user)) { @@ -206,7 +208,7 @@ namespace Back.Program.Services.V1 _logger.LogInformation($"[{summary}]: 성공 - 로그 저장 실패"); } - return APIResponse.Send("000", $"[{summary}], 정상", new {}); + return APIResponse.Send("000", $"[{summary}], 정상", new { }); } else { @@ -233,90 +235,12 @@ namespace Back.Program.Services.V1 var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var user = await _userRepository.FindUser(uid); - if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new {}); + if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new { }); var academyList = await _userRepository.FindAcademies(uid); _logger.LogInformation($"[{summary}]: 성공"); return APIResponse.Send("000", $"[{summary}], 정상.", academyList); } - - public async Task> GetSessionData(string summary) - { - try - { - _logger.LogInformation($"[{summary}] 세션 데이터 조회 시작"); - - // 1. 세션에서 토큰 가져오기 - var (result, token) = await _sessionService.GetString("token"); - _logger.LogInformation($"[{summary}] 세션에서 토큰 가져오기 결과: {result}, 토큰: {token}"); - - if (!result || string.IsNullOrEmpty(token)) - { - _logger.LogWarning($"[{summary}] 세션에 토큰이 없습니다"); - return APIResponse.Send("200", "세션에 토큰이 없습니다", new { }); - } - - // 2. 토큰 검증 - var validToken = await _jwtTokenService.ValidateToken(token); - _logger.LogInformation($"[{summary}] 토큰 검증 결과: {validToken != null}"); - - if (validToken == null) - { - // 3. 토큰이 유효하지 않으면 리프레시 토큰으로 새 토큰 발급 시도 - var (refreshResult, refreshToken) = await _sessionService.GetString("refresh"); - _logger.LogInformation($"[{summary}] 리프레시 토큰 가져오기 결과: {refreshResult}, 토큰: {refreshToken}"); - - if (!refreshResult || string.IsNullOrEmpty(refreshToken)) - { - _logger.LogWarning($"[{summary}] 리프레시 토큰이 없습니다"); - return APIResponse.Send("201", "리프레시 토큰이 없습니다", new { }); - } - - // 4. 리프레시 토큰으로 새 토큰 발급 - var retryResult = await _appService.RetryAccess(summary, refreshToken); - _logger.LogInformation($"[{summary}] 토큰 재발급 결과: {retryResult.status.code}"); - - if (retryResult.status.code == "000") - { - // 5. 새 토큰을 세션에 저장 - var data = JsonSerializer.Deserialize(JsonSerializer.Serialize(retryResult.data)); - var newToken = data.GetProperty("access").GetString(); - await _sessionService.SetString("token", newToken); - _logger.LogInformation($"[{summary}] 새 토큰 세션 저장 완료"); - - // 6. 새 토큰으로 사용자 정보 조회 - validToken = await _jwtTokenService.ValidateToken(newToken); - } - else - { - _logger.LogWarning($"[{summary}] 토큰 갱신 실패: {retryResult.status.message}"); - return APIResponse.Send("202", "토큰 갱신 실패", new { }); - } - } - - // 7. 최종적으로 유효한 토큰으로 사용자 정보 조회 - var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; - _logger.LogInformation($"[{summary}] 사용자 ID: {uid}"); - - var user = await _userRepository.FindUser(uid); - _logger.LogInformation($"[{summary}] 사용자 정보 조회 결과: {user != null}"); - - if (user == null) - { - _logger.LogWarning($"[{summary}] 사용자 정보를 찾을 수 없습니다"); - return APIResponse.Send("203", "사용자 정보를 찾을 수 없습니다", new { }); - } - - _logger.LogInformation($"[{summary}] 세션 데이터 조회 성공: {user.name}"); - return APIResponse.Send("000", $"[{summary}], 정상", user); - } - catch (Exception ex) - { - _logger.LogError($"[{summary}] 세션 데이터 조회 중 오류: {ex.Message}"); - _logger.LogError($"[{summary}] 스택 트레이스: {ex.StackTrace}"); - return APIResponse.InternalSeverError($"[{summary}], 세션 데이터 조회 실패"); - } - } } } \ No newline at end of file