main #49
|
@ -22,6 +22,8 @@ namespace Back.Program.Common.Auth
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// JWT 토큰 생성
|
||||||
public string GenerateJwtToken(string jwtKey)//, string role)
|
public string GenerateJwtToken(string jwtKey)//, string role)
|
||||||
{
|
{
|
||||||
// 1. 클레임(Claim) 설정 - 필요에 따라 추가 정보도 포함
|
// 1. 클레임(Claim) 설정 - 필요에 따라 추가 정보도 포함
|
||||||
|
@ -53,6 +55,7 @@ namespace Back.Program.Common.Auth
|
||||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 리프레시 토큰 생성
|
||||||
public RefreshToken GenerateRefreshToken(string uid)
|
public RefreshToken GenerateRefreshToken(string uid)
|
||||||
{
|
{
|
||||||
var randomNumber = new byte[32]; // 256비트
|
var randomNumber = new byte[32]; // 256비트
|
||||||
|
|
|
@ -10,6 +10,8 @@ using Back.Program.Models.APIResponses;
|
||||||
|
|
||||||
namespace Back.Program.Controllers;
|
namespace Back.Program.Controllers;
|
||||||
|
|
||||||
|
|
||||||
|
// TO-DO: 여기 controller, service, repository 분리 필요
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("/api/v1/out/user")]
|
[Route("/api/v1/out/user")]
|
||||||
[ApiExplorerSettings(GroupName = "외부 동작(사용자)")]
|
[ApiExplorerSettings(GroupName = "외부 동작(사용자)")]
|
||||||
|
@ -48,48 +50,63 @@ public class OutController: ControllerBase
|
||||||
[HttpGet("kakao/redirect")]
|
[HttpGet("kakao/redirect")]
|
||||||
public async Task<IActionResult> RedirectFromKakao([FromQuery] string code)
|
public async Task<IActionResult> RedirectFromKakao([FromQuery] string code)
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("카카오 리다이렉트 시작");
|
||||||
var (success, response) = await _kakaoService.Redirect(code);
|
var (success, response) = await _kakaoService.Redirect(code);
|
||||||
Console.WriteLine($"리다이렉트 : {response}");
|
_logger.LogInformation($"리다이렉트 결과: {success}, 응답: {response}");
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
var (idSuccess, idResponse) = await _kakaoService.UserMe(response);
|
var (idSuccess, idResponse) = await _kakaoService.UserMe(response);
|
||||||
|
_logger.LogInformation($"사용자 정보 조회 결과: {idSuccess}, 응답: {idResponse}");
|
||||||
|
|
||||||
if (idSuccess)
|
if (idSuccess)
|
||||||
{
|
{
|
||||||
var json = JsonDocument.Parse(idResponse);
|
var json = JsonDocument.Parse(idResponse);
|
||||||
if (json.RootElement.TryGetProperty("id", out var idElement))
|
if (json.RootElement.TryGetProperty("id", out var idElement))
|
||||||
{
|
{
|
||||||
var snsId = idElement.ToString();
|
var snsId = idElement.ToString();
|
||||||
Console.WriteLine($"ID = {snsId}");
|
_logger.LogInformation($"카카오 ID: {snsId}");
|
||||||
|
|
||||||
var loginResult = await _userService.Login("SNS Login", "ST01", snsId);
|
var loginResult = await _userService.Login("SNS Login", "ST01", snsId);
|
||||||
Console.WriteLine($"login = {loginResult.JsonToString()}");
|
_logger.LogInformation($"로그인 결과: {loginResult.JsonToString()}");
|
||||||
|
|
||||||
if (loginResult.status.code == "000")
|
if (loginResult.status.code == "000")
|
||||||
{
|
{
|
||||||
var data = loginResult.data as LoginAPIResponse ?? new LoginAPIResponse();
|
var data = JsonSerializer.Deserialize<LoginAPIResponse>(JsonSerializer.Serialize(loginResult.data));
|
||||||
|
_logger.LogInformation($"로그인 데이터: {JsonSerializer.Serialize(data)}");
|
||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
string token = data.token;
|
string token = data.token;
|
||||||
string refresh = data.refresh;
|
string refresh = data.refresh;
|
||||||
|
_logger.LogInformation($"토큰 저장 시도 - token: {token}, refresh: {refresh}");
|
||||||
|
|
||||||
if (await _sessionService.SetString("token", token) &&
|
if (await _sessionService.SetString("token", token) &&
|
||||||
await _sessionService.SetString("refresh", refresh))
|
await _sessionService.SetString("refresh", refresh))
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("세션 저장 성공");
|
||||||
var (hasPath, redirectPath) = await _sessionService.GetString("redirectPath");
|
var (hasPath, redirectPath) = await _sessionService.GetString("redirectPath");
|
||||||
await _sessionService.Remove("redirectPath"); // 사용 후 세션에서 제거
|
await _sessionService.Remove("redirectPath"); // 사용 후 세션에서 제거
|
||||||
|
|
||||||
// 로그인 성공 flag 쿠키 저장
|
var redirectUrl = hasPath && !string.IsNullOrEmpty(redirectPath)
|
||||||
Response.Cookies.Append("IsLogin", "true", new CookieOptions
|
? $"{redirectPath}?auth=true"
|
||||||
{
|
: "/about?auth=true";
|
||||||
HttpOnly = false,
|
_logger.LogInformation($"리다이렉트 URL: {redirectUrl}");
|
||||||
Secure = true,
|
return Redirect(redirectUrl);
|
||||||
SameSite = SameSiteMode.Lax,
|
|
||||||
Path = "/",
|
|
||||||
Expires = DateTime.Now.AddDays(1)
|
|
||||||
});
|
|
||||||
return Redirect(hasPath && !string.IsNullOrEmpty(redirectPath) ? redirectPath : "/about");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("세션 저장 실패");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("로그인 데이터가 null입니다");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (loginResult.status.code == "001")
|
else if (loginResult.status.code == "001")
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("회원가입 필요");
|
||||||
if (await _sessionService.SetString("snsId", snsId))
|
if (await _sessionService.SetString("snsId", snsId))
|
||||||
{
|
{
|
||||||
return Redirect("/auth/register");
|
return Redirect("/auth/register");
|
||||||
|
@ -97,11 +114,23 @@ public class OutController: ControllerBase
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_logger.LogError($"로그인 실패: {loginResult.status.message}");
|
||||||
return BadRequest(new { error = "로그인 실패", message = loginResult.status.message });
|
return BadRequest(new { error = "로그인 실패", message = loginResult.status.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("카카오 ID를 찾을 수 없습니다");
|
||||||
}
|
}
|
||||||
Console.WriteLine($"ID_res = {idResponse}");
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError($"사용자 정보 조회 실패: {idResponse}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError($"카카오 리다이렉트 실패: {response}");
|
||||||
}
|
}
|
||||||
return BadRequest();
|
return BadRequest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,10 +106,14 @@ namespace Back.Program.Controllers.V1
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("auth/session")]
|
||||||
|
[CustomOperation("세션 정보 확인", "세션 정보 확인", "사용자")]
|
||||||
|
public async Task<IActionResult> GetSessionData()
|
||||||
|
{
|
||||||
|
string summary = _repositoryService.ReadSummary(typeof(UserController), "GetSessionData");
|
||||||
|
var result = await _userService.GetSessionData(summary);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,11 +158,11 @@ public class AppService: IAppService
|
||||||
{
|
{
|
||||||
var refreshToken = await _appRepository.FindRefreshToken(refresh);
|
var refreshToken = await _appRepository.FindRefreshToken(refresh);
|
||||||
if (refreshToken == null) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 문제");
|
if (refreshToken == null) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 문제");
|
||||||
if (refreshToken.revoke_Date < DateTime.Now) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 만료");
|
if (refreshToken.revoke_Date != null) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 폐기");
|
||||||
if (refreshToken.expire_date < DateTime.Now) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 폐기");
|
if (refreshToken.expire_date < DateTime.Now) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 만료");
|
||||||
|
|
||||||
string access = _jwtTokenService.GenerateJwtToken(refreshToken.uid);
|
string access = _jwtTokenService.GenerateJwtToken(refreshToken.uid);
|
||||||
return APIResponse.Send<object>("000", $"[{summary}], 토큰 생성 완료", new { accsee = access });
|
return APIResponse.Send<object>("000", $"[{summary}], 토큰 생성 완료", new { access = access });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -11,6 +11,6 @@ namespace Back.Program.Services.V1.Interfaces
|
||||||
Task<APIResponseStatus<object>> Logout(string summary, string token);
|
Task<APIResponseStatus<object>> Logout(string summary, string token);
|
||||||
Task<APIResponseStatus<object>> Cancel(string summary, string token);
|
Task<APIResponseStatus<object>> Cancel(string summary, string token);
|
||||||
Task<APIResponseStatus<object>> GetAcademy(string summary, string token);
|
Task<APIResponseStatus<object>> GetAcademy(string summary, string token);
|
||||||
|
Task<APIResponseStatus<object>> GetSessionData(string summary);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using Back.Program.Common.Model;
|
||||||
using Back.Program.Models.Entities;
|
using Back.Program.Models.Entities;
|
||||||
using Back.Program.Repositories.V1.Interfaces;
|
using Back.Program.Repositories.V1.Interfaces;
|
||||||
using Back.Program.Services.V1.Interfaces;
|
using Back.Program.Services.V1.Interfaces;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Back.Program.Services.V1
|
namespace Back.Program.Services.V1
|
||||||
{
|
{
|
||||||
|
@ -14,16 +15,21 @@ namespace Back.Program.Services.V1
|
||||||
private readonly JwtTokenService _jwtTokenService;
|
private readonly JwtTokenService _jwtTokenService;
|
||||||
private readonly IRepositoryService _repositoryService;
|
private readonly IRepositoryService _repositoryService;
|
||||||
private readonly ILogRepository _logRepository;
|
private readonly ILogRepository _logRepository;
|
||||||
|
private readonly ISessionService _sessionService;
|
||||||
|
private readonly IAppService _appService;
|
||||||
|
|
||||||
public UserService(ILogger<IUserService> logger, IUserRepository userRepository,
|
public UserService(ILogger<IUserService> logger, IUserRepository userRepository,
|
||||||
JwtTokenService jwtTokenService,
|
JwtTokenService jwtTokenService,
|
||||||
IRepositoryService repositoryService, ILogRepository logRepository)
|
IRepositoryService repositoryService, ILogRepository logRepository,
|
||||||
|
ISessionService sessionService, IAppService appService)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_jwtTokenService = jwtTokenService;
|
_jwtTokenService = jwtTokenService;
|
||||||
_repositoryService = repositoryService;
|
_repositoryService = repositoryService;
|
||||||
_logRepository = logRepository;
|
_logRepository = logRepository;
|
||||||
|
_sessionService = sessionService;
|
||||||
|
_appService = appService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<APIResponseStatus<object>> GetUser(string summary, string token)
|
public async Task<APIResponseStatus<object>> GetUser(string summary, string token)
|
||||||
|
@ -234,5 +240,83 @@ namespace Back.Program.Services.V1
|
||||||
_logger.LogInformation($"[{summary}]: 성공");
|
_logger.LogInformation($"[{summary}]: 성공");
|
||||||
return APIResponse.Send<object>("000", $"[{summary}], 정상.", academyList);
|
return APIResponse.Send<object>("000", $"[{summary}], 정상.", academyList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<APIResponseStatus<object>> 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<object>("200", "세션에 토큰이 없습니다", new { name = "" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<object>("201", "리프레시 토큰이 없습니다", new { name = "" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 리프레시 토큰으로 새 토큰 발급
|
||||||
|
var retryResult = await _appService.RetryAccess(summary, refreshToken);
|
||||||
|
_logger.LogInformation($"[{summary}] 토큰 재발급 결과: {retryResult.status.code}");
|
||||||
|
|
||||||
|
if (retryResult.status.code == "000")
|
||||||
|
{
|
||||||
|
// 5. 새 토큰을 세션에 저장
|
||||||
|
var data = JsonSerializer.Deserialize<JsonElement>(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<object>("202", "토큰 갱신 실패", new { name = "" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<object>("203", "사용자 정보를 찾을 수 없습니다", new { name = "" });
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"[{summary}] 세션 데이터 조회 성공: {user.name}");
|
||||||
|
return APIResponse.Send<object>("000", $"[{summary}], 정상", new { name = user.name });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError($"[{summary}] 세션 데이터 조회 중 오류: {ex.Message}");
|
||||||
|
_logger.LogError($"[{summary}] 스택 트레이스: {ex.StackTrace}");
|
||||||
|
return APIResponse.InternalSeverError($"[{summary}], 세션 데이터 조회 실패");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user