diff --git a/src/main/java/com/sb/web/auth/dto/LoginRequest.java b/src/main/java/com/sb/web/auth/dto/LoginRequest.java index 0c11965..a9283c4 100644 --- a/src/main/java/com/sb/web/auth/dto/LoginRequest.java +++ b/src/main/java/com/sb/web/auth/dto/LoginRequest.java @@ -14,4 +14,7 @@ public class LoginRequest { @NotBlank(message = "비밀번호를 입력하세요.") private String password; + + /** 로그인 상태 유지(자동 로그인). true 면 세션을 길게(30일) 유지 */ + private boolean rememberMe; } diff --git a/src/main/java/com/sb/web/auth/dto/SessionUser.java b/src/main/java/com/sb/web/auth/dto/SessionUser.java index 7cf03b3..f96255d 100644 --- a/src/main/java/com/sb/web/auth/dto/SessionUser.java +++ b/src/main/java/com/sb/web/auth/dto/SessionUser.java @@ -23,6 +23,7 @@ public class SessionUser implements Serializable { private String name; private String role; private String provider; + private boolean rememberMe; // 자동 로그인 세션 여부 (슬라이딩 만료 TTL 결정용) public static SessionUser from(Member m) { return SessionUser.builder() diff --git a/src/main/java/com/sb/web/auth/service/AuthService.java b/src/main/java/com/sb/web/auth/service/AuthService.java index 33d528a..347a222 100644 --- a/src/main/java/com/sb/web/auth/service/AuthService.java +++ b/src/main/java/com/sb/web/auth/service/AuthService.java @@ -36,7 +36,8 @@ public class AuthService { private final RedisTemplate redisTemplate; private static final String SESSION_PREFIX = "session:"; - private static final Duration SESSION_TTL = Duration.ofMinutes(60); + private static final Duration SESSION_TTL = Duration.ofMinutes(60); // 일반 세션 + private static final Duration REMEMBER_TTL = Duration.ofDays(30); // 자동 로그인(로그인 상태 유지) @Transactional public MemberResponse signup(SignupRequest req) { @@ -68,13 +69,17 @@ public class AuthService { throw new ApiException(HttpStatus.FORBIDDEN, "사용할 수 없는 계정입니다."); } + Duration ttl = req.isRememberMe() ? REMEMBER_TTL : SESSION_TTL; + SessionUser session = SessionUser.from(member); + session.setRememberMe(req.isRememberMe()); + String token = UUID.randomUUID().toString().replace("-", ""); - redisTemplate.opsForValue().set(SESSION_PREFIX + token, SessionUser.from(member), SESSION_TTL); - log.info("[login] {} (token issued)", member.getLoginId()); + redisTemplate.opsForValue().set(SESSION_PREFIX + token, session, ttl); + log.info("[login] {} (token issued, rememberMe={})", member.getLoginId(), req.isRememberMe()); return LoginResponse.builder() .token(token) - .expiresInSeconds(SESSION_TTL.getSeconds()) + .expiresInSeconds(ttl.getSeconds()) .member(MemberResponse.from(member)) .build(); } @@ -89,7 +94,8 @@ public class AuthService { String key = SESSION_PREFIX + token; Object cached = redisTemplate.opsForValue().get(key); if (cached instanceof SessionUser user) { - redisTemplate.expire(key, SESSION_TTL); + // 슬라이딩 만료: 자동 로그인 세션이면 길게(30일), 아니면 60분으로 갱신 + redisTemplate.expire(key, user.isRememberMe() ? REMEMBER_TTL : SESSION_TTL); return user; } return null;