package com.takensoft.common.util; import com.fasterxml.jackson.databind.ObjectMapper; import com.takensoft.cms.loginPolicy.service.LoginModeService; import com.takensoft.cms.loginPolicy.service.LoginPolicyService; import com.takensoft.cms.mber.service.LgnHstryService; import com.takensoft.cms.mber.vo.LgnHstryVO; import com.takensoft.cms.mber.vo.MberVO; import com.takensoft.cms.token.service.RefreshTokenService; import com.takensoft.cms.token.vo.RefreshTknVO; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Component @RequiredArgsConstructor public class LoginUtil { private final LgnHstryService lgnHstryService; private final HttpRequestUtil httpRequestUtil; private final LoginModeService loginModeService; private final RefreshTokenService refreshTokenService; private final LoginPolicyService loginPolicyService; private final JWTUtil jwtUtil; private final SessionUtil sessionUtil; private final RedisTemplate redisTemplate; @Value("${jwt.accessTime}") private long JWT_ACCESSTIME; // access 토큰 유지 시간 @Value("${jwt.refreshTime}") private long JWT_REFRESHTIME; // refresh 토큰 유지 시간 @Value("${cookie.time}") private int COOKIE_TIME; // 쿠키 유지 시간 public void successLogin(MberVO mber, HttpServletRequest req, HttpServletResponse res) { try { // 로그인 이력 등록 LgnHstryVO lgnHstryVO = new LgnHstryVO(); lgnHstryVO.setLgnId(mber.getLgnId()); lgnHstryVO.setLgnType(mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN")) ? "0" : "1"); lgnHstryVO.setCntnIp(httpRequestUtil.getIp(req)); lgnHstryVO.setCntnOperSys(httpRequestUtil.getOS(httpRequestUtil.getUserAgent(req))); lgnHstryVO.setDeviceNm(httpRequestUtil.getDevice(httpRequestUtil.getUserAgent(req))); lgnHstryVO.setBrwsrNm(httpRequestUtil.getBrowser(httpRequestUtil.getUserAgent(req))); lgnHstryService.LgnHstrySave(lgnHstryVO); // 로그인 방식 확인 JWT or SESSION String loginType = loginModeService.getLoginMode(); // 토큰 생성(access, refresh) String accessToken = jwtUtil.createJwt("Authorization", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_ACCESSTIME); String refreshToken = jwtUtil.createJwt("refresh", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_REFRESHTIME); // refreshToken이 현재 IP와 계정으로 등록되어 있는지 확인 RefreshTknVO refresh = new RefreshTknVO(); refresh.setMbrId(mber.getMbrId()); // refresh 토큰이 현재 아이피와 아이디로 DB에 등록 되어 있다면 if (refreshTokenService.findByCheckRefresh(req, refresh)) { refreshTokenService.delete(req, refresh); } // refreshToken DB 저장 refresh.setToken(refreshToken); if ("S".equals(loginType)) { HttpSession session = req.getSession(true); session.setAttribute("JWT_TOKEN", accessToken); // 중복 로그인 비허용일 때 기존 세션 만료 if (!loginPolicyService.getPolicy()) { sessionUtil.registerSession(mber.getMbrId(), session); } Map result = new HashMap<>(); result.put("mbrId", mber.getMbrId()); result.put("mbrNm", mber.getMbrNm()); result.put("roles", mber.getAuthorList()); res.setContentType("application/json;charset=UTF-8"); res.setStatus(HttpStatus.OK.value()); new ObjectMapper().writeValue(res.getOutputStream(), result); } else { res.setHeader("Authorization", accessToken); res.addCookie(jwtUtil.createCookie("refresh", refreshToken, COOKIE_TIME)); // 중복 로그인 비허용일 때 Redis 저장 if (!loginPolicyService.getPolicy()) { redisTemplate.delete("jwt:" + mber.getMbrId()); redisTemplate.opsForValue().set("jwt:" + mber.getMbrId(), accessToken, JWT_ACCESSTIME, TimeUnit.MILLISECONDS); } } refreshTokenService.saveRefreshToken(req, res, refresh, JWT_REFRESHTIME); res.setHeader("login-type", loginType); } catch (IOException ioe) { throw new RuntimeException(ioe); } catch (Exception e) { throw e; } } }