From 65962c01c2f78e562ab145404d7f3671568ab6e4 Mon Sep 17 00:00:00 2001 From: "Seonkyu.kim" Date: Thu, 29 May 2025 17:53:50 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[=E2=9C=A8]=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 인가코드 받기 2. 리다이렉트 -> 인가 코드를 엑세스 토큰으로 3. User.Me -> snsID 받아오기 4. DB 에서 snsID 조회 까지 완료 --- Back.csproj | 7 ++ Program.cs | 2 +- Program/Common/Auth/APIHeaderMiddleware.cs | 14 ++-- Program/Controllers/V1/OutController.cs | 64 ++++++++++++++++++ Program/Controllers/V1/UserController.cs | 16 ++--- .../Services/V1/Interfaces/IKakaoService.cs | 1 + Program/Services/V1/KakaoService.cs | 22 ++++++ Program/Services/V1/RepositoryService.cs | 67 ++++--------------- appsettings.Development.json | 11 ++- appsettings.json | 12 ++-- 10 files changed, 138 insertions(+), 78 deletions(-) create mode 100644 Program/Controllers/V1/OutController.cs diff --git a/Back.csproj b/Back.csproj index b289ad8..09c7865 100644 --- a/Back.csproj +++ b/Back.csproj @@ -20,6 +20,13 @@ + + + + + + <_ContentIncludedByDefault Remove="wwwroot\css\app.css" /> + <_ContentIncludedByDefault Remove="wwwroot\css\tailwind.css" /> diff --git a/Program.cs b/Program.cs index 58404cd..eb7e97d 100644 --- a/Program.cs +++ b/Program.cs @@ -127,7 +127,7 @@ 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/APIHeaderMiddleware.cs b/Program/Common/Auth/APIHeaderMiddleware.cs index a4a26fb..f128074 100644 --- a/Program/Common/Auth/APIHeaderMiddleware.cs +++ b/Program/Common/Auth/APIHeaderMiddleware.cs @@ -24,6 +24,13 @@ namespace Back.Program.Common.Auth await _next(context); return; } + + if (context.Request.Path.Value != null && context.Request.Path.Value.Contains("/out/")) + { + await _next(context); + return; + } + // 정적 파일 요청은 미들웨어 건너뜀 var path = context.Request.Path.Value; @@ -58,12 +65,11 @@ namespace Back.Program.Common.Auth } await _next(context); - } - - { - await _next(context); return; } + + await _next(context); + } } } \ No newline at end of file diff --git a/Program/Controllers/V1/OutController.cs b/Program/Controllers/V1/OutController.cs new file mode 100644 index 0000000..b5bbfc8 --- /dev/null +++ b/Program/Controllers/V1/OutController.cs @@ -0,0 +1,64 @@ +using System.Text.Json; +using Back.Program.Controllers.V1; +using Back.Program.Services.V1; +using Back.Program.Services.V1.Interfaces; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; + +namespace Back.Program.Controllers; + +[ApiController] +[Route("/api/v1/out/user")] +[ApiExplorerSettings(GroupName = "외부 동작(사용자)")] +public class OutController: ControllerBase +{ + private readonly ILogger _logger; + private readonly IRepositoryService _repositoryService; + private readonly IUserService _userService; + private readonly IKakaoService _kakaoService; + + public OutController(ILogger logger, + IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService) + { + _logger = logger; + _repositoryService = repositoryService; + _userService = userService; + _kakaoService = kakaoService; + } + [HttpGet("kakao/auth")] + [CustomOperation("카카오 로그인", "카카오 로그인 동작", "사용자")] + public async Task KakaoLogin([FromQuery] string? scope) + { + var url = await _kakaoService.GetAuthorizationUrl(scope ?? ""); + Console.WriteLine($"카카오 로그인 API: {url}"); + return Ok(new { url }); + } + + [HttpGet("kakao/redirect")] + public async Task RedirectFromKakao([FromQuery] string code) + { + var (success, response) = await _kakaoService.Redirect(code); + Console.WriteLine($"리다이렉트 : {response}"); + if (success) + { + // HttpContext.Session.SetString("AccessToken", response); + var (idSuccess, idResponse) = await _kakaoService.UserMe(response); + if (idSuccess) + { + var json = JsonDocument.Parse(idResponse); + if (json.RootElement.TryGetProperty("id", out var idElement)) + { + var snsId = idElement.ToString(); + Console.WriteLine($"ID = {snsId}"); + var loginResult = await _userService.Login("SNS Login", "ST01", snsId); + Console.WriteLine($"login = {loginResult.JsonToString()}"); + // return Ok(new { id="cc" }); + } + } + Console.WriteLine($"ID_res = {idResponse}"); + + } + return BadRequest(); + + } +} \ No newline at end of file diff --git a/Program/Controllers/V1/UserController.cs b/Program/Controllers/V1/UserController.cs index b4ec050..93fe848 100644 --- a/Program/Controllers/V1/UserController.cs +++ b/Program/Controllers/V1/UserController.cs @@ -5,6 +5,7 @@ using Back.Program.Common.Model; using Back.Program.Models.Entities; using Back.Program.Services.V1.Interfaces; using Back.Program.Services.V1; +using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -21,7 +22,6 @@ namespace Back.Program.Controllers.V1 private readonly ILogger _logger; private readonly IRepositoryService _repositoryService; private readonly IUserService _userService; - private readonly IKakaoService _kakaoService; public UserController(ILogger logger, IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService) @@ -29,7 +29,6 @@ namespace Back.Program.Controllers.V1 _logger = logger; _repositoryService = repositoryService; _userService = userService; - _kakaoService = kakaoService; } [HttpGet] @@ -106,15 +105,12 @@ namespace Back.Program.Controllers.V1 var result = await _userService.GetAcademy(summary, token); return Ok(result); } + + - [HttpGet("kakao/auth")] - [CustomOperation("카카오 로그인", "카카오 로그인 동작", "사용자")] - public async Task KakaoLogin([FromQuery] string scope) - { - var authUrl = await _kakaoService.GetAuthorizationUrl(scope); - return Redirect(authUrl); - } + + } } @@ -122,7 +118,7 @@ namespace Back.Program.Controllers.V1 // 근데 회원 정보를 변경하는게 뭐뭐를 변경해야 하는지 아직 정해진게 없어서 이건 일단 보류 /* [HttpGet("set")] - [CustomOperation("회원 정보 변경", "회원 정보 변경", "사용자")] + [CustomOperation("회원 정보 변경", "회원 정보 변경", "사혹자")] public async Task SetUserData(string token, string refresh) //, [FromBody]) { if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) diff --git a/Program/Services/V1/Interfaces/IKakaoService.cs b/Program/Services/V1/Interfaces/IKakaoService.cs index e24f23e..d3ae355 100644 --- a/Program/Services/V1/Interfaces/IKakaoService.cs +++ b/Program/Services/V1/Interfaces/IKakaoService.cs @@ -9,4 +9,5 @@ public interface IKakaoService Task<(bool Success, string Response)> Redirect(string code); Task<(bool Success, string Response)> Logout(string accessToken); Task<(bool Success, string Response)> Unlink(string accessToken); + Task<(bool Success, string Response)> UserMe(string accessToken); } \ No newline at end of file diff --git a/Program/Services/V1/KakaoService.cs b/Program/Services/V1/KakaoService.cs index efffa87..05ad33d 100644 --- a/Program/Services/V1/KakaoService.cs +++ b/Program/Services/V1/KakaoService.cs @@ -53,6 +53,11 @@ public class KakaoService: IKakaoService } } + /// + /// 인가 받은 코드로 토큰 받기를 실행하고 이 토큰으로 사용자 정보 가져오기를 할 수 있다. + /// + /// + /// public async Task GetAccessToken(string code) { var content = new FormUrlEncodedContent(new[] @@ -81,6 +86,13 @@ public class KakaoService: IKakaoService return JsonSerializer.Serialize(new { access_token = accessToken.GetString() }); } + + /// + /// 인가코드를 받는다 이 인가코드를 사용해 토큰 받기를 요청 할 수 있다. + /// 이게 리다이렉트에 포함되어있음 + /// + /// + /// public Task GetAuthorizationUrl(string scope) { var authUrl = $"{KAKAO_AUTH_BASE_URL}/oauth/authorize?client_id={_clientId}&redirect_uri={_redirectUri}&response_type=code"; @@ -132,4 +144,14 @@ public class KakaoService: IKakaoService var response = await Call(HttpMethod.Post, $"{KAKAO_API_BASE_URL}/v1/user/unlink"); return (true, response); } + + public async Task<(bool Success, string Response)> UserMe(string accessToken) + { + if (string.IsNullOrEmpty(accessToken)) + return (false, JsonSerializer.Serialize(new { error = "Not logged in" })); + + SetHeaders(accessToken); + var response = await Call(HttpMethod.Get, $"{KAKAO_API_BASE_URL}/v2/user/me"); + return (true, response); + } } \ No newline at end of file diff --git a/Program/Services/V1/RepositoryService.cs b/Program/Services/V1/RepositoryService.cs index 9313c4a..875ac1b 100644 --- a/Program/Services/V1/RepositoryService.cs +++ b/Program/Services/V1/RepositoryService.cs @@ -1,5 +1,7 @@ using System.Linq.Expressions; using System.Reflection; +using System.Text; +using System.Text.Json; using Back.Program.Common.Auth; using Back.Program.Common.Data; using Back.Program.Common.Model; @@ -14,6 +16,7 @@ namespace Back.Program.Services.V1 Task SaveData(T entity, Expression> key = null) where T : class; Task DeleteData(T entity, Expression> key = null) where T : class; String ReadSummary(Type type, String name); + Task SendFrontData(T data, string url); } public class RepositoryService: IRepositoryService @@ -28,61 +31,6 @@ namespace Back.Program.Services.V1 _logger = logger; _jwtTokenService = jwtTokenService; } - - - // public async Task ValidateToken(string token, string refresh) - // { - // var principalToken = await _jwtTokenService.ValidateToken(token); - // if (principalToken != null) - // { - // var uid = principalToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; - // _logger.LogInformation($"토큰 변환 - {uid}"); - // return new ValidateToken - // { - // token = token, - // refresh = refresh, - // uid = uid - // }; - // } - // else - // { - // _logger.LogInformation("엑세스 토큰 만료"); - // // var refreshToken = await _dbContext.RefreshTokens - // // .FirstOrDefaultAsync(t => t.refresh_token == refresh); - // // if (refreshToken == null) - // // throw new TokenException("입력 받은 토큰 자체의 문제"); - // // - // // var uid = refreshToken.uid; - // // - // // if (refreshToken.revoke_Date < DateTime.Now) - // // throw new RefreshRevokeException("리프레시 토큰 해지"); - // // - // // if (refreshToken.expire_date > DateTime.Now) - // // { - // // _logger.LogInformation($"인증 완료 리프레시 : {uid}"); - // // var access = _jwtTokenService.GenerateJwtToken(uid); - // // - // // return new ValidateToken - // // { - // // token = access, - // // refresh = refreshToken.refresh_token, - // // uid = uid - // // }; - // // } - // // else - // // { - // // refreshToken = _jwtTokenService.GenerateRefreshToken(uid); - // // _logger.LogInformation("리프레시 토큰 만료"); - // // // await SaveData(refreshToken, rt => rt.uid); - // // return new ValidateToken - // // { - // // token = token, - // // refresh = refreshToken.refresh_token, - // // uid = uid - // // }; - // // } - // } - // } public async Task SaveData(T entity, Expression> key = null) where T : class { @@ -227,5 +175,14 @@ namespace Back.Program.Services.V1 var att = method.GetCustomAttribute() ?? throw new AcaException(ResposeCode.NetworkErr,"swagger summary Load ERROR: NULL"); return att.Summary; } + + public async Task SendFrontData(T data, string url) + { + using var httpClient = new HttpClient(); + var json = JsonSerializer.Serialize(data); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + var response = await httpClient.PostAsync(url, content); + response.EnsureSuccessStatusCode(); + } } } diff --git a/appsettings.Development.json b/appsettings.Development.json index ff14d6a..56092aa 100644 --- a/appsettings.Development.json +++ b/appsettings.Development.json @@ -7,8 +7,15 @@ }, "PushFileSetting": { "uri": "https://api.sandbox.push.apple.com/", - "p12Path": "/src/private/AM_Push_Sandbox.p12", - "p12PWPath": "/src/private/appleKeys.json", + "p12Path": "./private/AM_Push_Sandbox.p12", + "p12PWPath": "./private/appleKeys.json", "apnsTopic": "me.myds.ipstein.acamate.AcaMate" + }, + "AllowedHosts": "*", + "Kakao": { + "ClientId": "a9632e6c14d8706ef6c8fe2ef52b721d", + "ClientSecret": " this is rest api secret key ", + "RedirectUri": "http://0.0.0.0:5144/api/v1/out/user/kakao/redirect" +// "RedirectUri": "https://acamate.ipstein.com/kakao" } } diff --git a/appsettings.json b/appsettings.json index 056faaf..0d1d341 100644 --- a/appsettings.json +++ b/appsettings.json @@ -11,10 +11,10 @@ "P12PWPath": "/src/private/appleKeys.json", "ApnsTopic": "me.myds.ipstein.acamate.AcaMate" }, - "AllowedHosts": "*" -// "Kakao": { -// "ClientId": "a9632e6c14d8706ef6c8fe2ef52b721d", -// "ClientSecret": " this is rest api secret key ", -// "RedirectUri": "https://acamate.ipstein.com/kakao" -// } + "AllowedHosts": "*", + "Kakao": { + "ClientId": "a9632e6c14d8706ef6c8fe2ef52b721d", + "ClientSecret": " this is rest api secret key ", + "RedirectUri": "https://acamate.ipstein.com/kakao" + } } \ No newline at end of file -- 2.45.1 From 3ebb7137c09f626e1bdb715e3c127b073711d813 Mon Sep 17 00:00:00 2001 From: "Seonkyu.kim" Date: Fri, 30 May 2025 17:50:06 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[=E2=9C=A8]=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 카카오 로그인 인증 snsID 받아오기 2. 리다이렉트 동작 수정 3. 세션을 통한 토큰 저장 3.1. 세션서비스 생성 4. 회원가입 화면으로 이동 --- Program.cs | 6 +++ Program/Controllers/V1/AppController.cs | 15 ++++-- Program/Controllers/V1/OutController.cs | 39 +++++++++++++-- Program/Models/APIResponses/API_User.cs | 7 +++ .../V1/Interfaces/IRepositoryService.cs | 12 +++++ .../Services/V1/Interfaces/ISessionService.cs | 8 +++ Program/Services/V1/RepositoryService.cs | 10 +--- Program/Services/V1/SessionService.cs | 50 +++++++++++++++++++ 8 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 Program/Models/APIResponses/API_User.cs create mode 100644 Program/Services/V1/Interfaces/IRepositoryService.cs create mode 100644 Program/Services/V1/Interfaces/ISessionService.cs create mode 100644 Program/Services/V1/SessionService.cs diff --git a/Program.cs b/Program.cs index eb7e97d..91e937d 100644 --- a/Program.cs +++ b/Program.cs @@ -118,12 +118,17 @@ builder.Services.AddHostedService(); // PUSH 설정부 끝 builder.Services.AddControllers(); +// 세션 설정 +// IN-MEMORY 캐시 +builder.Services.AddDistributedMemoryCache(); +builder.Services.AddSession(); // ==== SCOPED 으로 등록 할 서비스 ==== // // 여기다가 API 있는 컨트롤러들 AddScoped 하면 되는건가? builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -215,6 +220,7 @@ app.UseStaticFiles(new StaticFileOptions }); app.UseRouting(); +app.UseSession(); app.UseCors("CorsPolicy"); app.UseAuthentication(); app.UseAuthorization(); diff --git a/Program/Controllers/V1/AppController.cs b/Program/Controllers/V1/AppController.cs index 4d53461..e92a67a 100644 --- a/Program/Controllers/V1/AppController.cs +++ b/Program/Controllers/V1/AppController.cs @@ -25,8 +25,9 @@ namespace Back.Program.Controllers.V1 private readonly JwtTokenService _jwtTokenService; private readonly IAppService _appService; private readonly IAppRepository _appRepository; + private readonly ISessionService _sessionService; - public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService,IAppService appService, IAppRepository appRepository) + public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService,IAppService appService, IAppRepository appRepository, ISessionService sessionService) { _dbContext = dbContext; _logger = logger; @@ -34,6 +35,7 @@ namespace Back.Program.Controllers.V1 _jwtTokenService = jwtTokenService; _appService = appService; _appRepository = appRepository; + _sessionService = sessionService; } @@ -70,9 +72,14 @@ namespace Back.Program.Controllers.V1 var result = await _appService.RetryAccess(summary, refresh); return Ok(result); } - - - + + [HttpGet("session")] + [CustomOperation("세션 정보 읽어오기", "세션 정보를 읽어오는 동작 수행", "시스템")] + public async Task GetSessionData(string key) + { + var value = _sessionService.GetString(key); + return Ok(new {key = value}); + } } } diff --git a/Program/Controllers/V1/OutController.cs b/Program/Controllers/V1/OutController.cs index b5bbfc8..781c51c 100644 --- a/Program/Controllers/V1/OutController.cs +++ b/Program/Controllers/V1/OutController.cs @@ -1,9 +1,12 @@ using System.Text.Json; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; + +using Back.Program.Common.Model; using Back.Program.Controllers.V1; using Back.Program.Services.V1; using Back.Program.Services.V1.Interfaces; -using Microsoft.AspNetCore.Http.HttpResults; -using Microsoft.AspNetCore.Mvc; +using Back.Program.Models.APIResponses; namespace Back.Program.Controllers; @@ -16,14 +19,16 @@ public class OutController: ControllerBase private readonly IRepositoryService _repositoryService; private readonly IUserService _userService; private readonly IKakaoService _kakaoService; + private readonly ISessionService _sessionService; public OutController(ILogger logger, - IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService) + IRepositoryService repositoryService, IUserService userService, IKakaoService kakaoService, ISessionService sessionService) { _logger = logger; _repositoryService = repositoryService; _userService = userService; _kakaoService = kakaoService; + _sessionService = sessionService; } [HttpGet("kakao/auth")] [CustomOperation("카카오 로그인", "카카오 로그인 동작", "사용자")] @@ -49,9 +54,35 @@ public class OutController: ControllerBase if (json.RootElement.TryGetProperty("id", out var idElement)) { var snsId = idElement.ToString(); - Console.WriteLine($"ID = {snsId}"); + Console.WriteLine($"ID = {snsId}"); var loginResult = await _userService.Login("SNS Login", "ST01", snsId); Console.WriteLine($"login = {loginResult.JsonToString()}"); + if (loginResult.status.code == "000") + { + + var data = loginResult.data as LoginAPIResponse ?? new LoginAPIResponse(); + if (data != null) + { + string token = data.token; + string refresh = data.refresh; + if (await _sessionService.SetString("token", token) && + await _sessionService.SetString("refresh", refresh)) + { + return Redirect("/about"); + } + } + } + else if (loginResult.status.code == "001") + { + if (await _sessionService.SetString("snsId", snsId)) + { + return Redirect("/auth/register"); + } + } + else + { + return BadRequest(new { error = "로그인 실패", message = loginResult.status.message }); + } // return Ok(new { id="cc" }); } } diff --git a/Program/Models/APIResponses/API_User.cs b/Program/Models/APIResponses/API_User.cs new file mode 100644 index 0000000..800c3a2 --- /dev/null +++ b/Program/Models/APIResponses/API_User.cs @@ -0,0 +1,7 @@ +namespace Back.Program.Models.APIResponses; + +public class LoginAPIResponse +{ + public string token { get; set; } = string.Empty; + public string refresh { get; set; } = string.Empty; +} diff --git a/Program/Services/V1/Interfaces/IRepositoryService.cs b/Program/Services/V1/Interfaces/IRepositoryService.cs new file mode 100644 index 0000000..7dd572f --- /dev/null +++ b/Program/Services/V1/Interfaces/IRepositoryService.cs @@ -0,0 +1,12 @@ +using System.Linq.Expressions; + +namespace Back.Program.Services.V1.Interfaces; + +public interface IRepositoryService +{ +// Task ValidateToken(string token, string refresh); + Task SaveData(T entity, Expression> key = null) where T : class; + Task DeleteData(T entity, Expression> key = null) where T : class; + String ReadSummary(Type type, String name); + Task SendFrontData(T data, string url); +} \ No newline at end of file diff --git a/Program/Services/V1/Interfaces/ISessionService.cs b/Program/Services/V1/Interfaces/ISessionService.cs new file mode 100644 index 0000000..b78b4ba --- /dev/null +++ b/Program/Services/V1/Interfaces/ISessionService.cs @@ -0,0 +1,8 @@ +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); +} \ No newline at end of file diff --git a/Program/Services/V1/RepositoryService.cs b/Program/Services/V1/RepositoryService.cs index 875ac1b..ea70168 100644 --- a/Program/Services/V1/RepositoryService.cs +++ b/Program/Services/V1/RepositoryService.cs @@ -6,19 +6,11 @@ using Back.Program.Common.Auth; using Back.Program.Common.Data; using Back.Program.Common.Model; using Back.Program.Models.Entities; +using Back.Program.Services.V1.Interfaces; using Microsoft.EntityFrameworkCore; namespace Back.Program.Services.V1 { - public interface IRepositoryService - { - // Task ValidateToken(string token, string refresh); - Task SaveData(T entity, Expression> key = null) where T : class; - Task DeleteData(T entity, Expression> key = null) where T : class; - String ReadSummary(Type type, String name); - Task SendFrontData(T data, string url); - } - public class RepositoryService: IRepositoryService { private readonly AppDbContext _dbContext; diff --git a/Program/Services/V1/SessionService.cs b/Program/Services/V1/SessionService.cs new file mode 100644 index 0000000..c876b2c --- /dev/null +++ b/Program/Services/V1/SessionService.cs @@ -0,0 +1,50 @@ +using Back.Program.Services.V1.Interfaces; + +namespace Back.Program.Services.V1; + +public class SessionService: ISessionService +{ + private readonly IHttpContextAccessor _http; + public SessionService(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 -- 2.45.1 From 1738878093913ba7f332007ba82e93159d57401f Mon Sep 17 00:00:00 2001 From: "Seonkyu.kim" Date: Wed, 4 Jun 2025 17:53:02 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[=E2=9C=A8]=20=EC=84=B8=EC=85=98=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 웹 - 서버 데이터 관리 위한 세션 관리 API 추가 --- Program/Common/Model/APISetting.cs | 27 +++++++++------ Program/Controllers/V1/AppController.cs | 45 ++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/Program/Common/Model/APISetting.cs b/Program/Common/Model/APISetting.cs index d1d4ac3..8417e9a 100644 --- a/Program/Common/Model/APISetting.cs +++ b/Program/Common/Model/APISetting.cs @@ -3,18 +3,23 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Back.Program.Common.Model { - [Table("api_header")] - public class APIHeader - { - [Key] - public string specific_id { get; set; } - - public DateTime connect_date { get; set; } - public string h_key { get; set; } - public string h_value { get; set; } - } -} + [Table("api_header")] + public class APIHeader + { + [Key] + public string specific_id { get; set; } + public DateTime connect_date { get; set; } + public string h_key { get; set; } + public string h_value { get; set; } + } + + public class SessionData + { + public string key { get; set; } + public string value { get; set; } + } +} /* h_key : h_value iOS_AM_Connect_Key diff --git a/Program/Controllers/V1/AppController.cs b/Program/Controllers/V1/AppController.cs index e92a67a..09946d1 100644 --- a/Program/Controllers/V1/AppController.cs +++ b/Program/Controllers/V1/AppController.cs @@ -72,13 +72,50 @@ namespace Back.Program.Controllers.V1 var result = await _appService.RetryAccess(summary, refresh); return Ok(result); } - - [HttpGet("session")] + + [HttpGet("session/get")] [CustomOperation("세션 정보 읽어오기", "세션 정보를 읽어오는 동작 수행", "시스템")] public async Task GetSessionData(string key) { - var value = _sessionService.GetString(key); - return Ok(new {key = value}); + if (string.IsNullOrEmpty(key)) + { + return BadRequest(APIResponse.InvalidInputError()); + } + + var (success, value) = await _sessionService.GetString(key); + if (!success) + { + return BadRequest(APIResponse.InvalidInputError()); + } + + string summary = _repositoryService.ReadSummary(typeof(AppController), "GetSessionData"); + return Ok(APIResponse.Send("000", $"[{summary}], 정상", new { data = value })); + } + + [HttpPost("session/set")] + [CustomOperation("세션 정보 저장하기", "세션 정보에 저장하는 동작 수행", "시스템")] + public async Task SetSessionData([FromBody] SessionData[] requests) + { + if(requests == null || requests.Length == 0) + { + return BadRequest(APIResponse.InvalidInputError()); + } + + Console.WriteLine($"받은 세션 데이터: {JsonSerializer.Serialize(requests)}"); + + foreach(var request in requests) + { + Console.WriteLine($"세션 저장 시도 - key: {request.key}, value: {request.value}"); + var success = await _sessionService.SetString(request.key, request.value); + if (!success) + { + Console.WriteLine($"세션 저장 실패 - key: {request.key}"); + return BadRequest(APIResponse.InvalidInputError()); + } + Console.WriteLine($"세션 저장 성공 - key: {request.key}"); + } + + return Ok(APIResponse.Send("000", $"[세션 저장]: 정상", new { })); } } } -- 2.45.1