로그인 기능 추가
This commit is contained in:
@@ -41,27 +41,27 @@ public class AuthController {
|
||||
private boolean refreshCookieSecure;
|
||||
|
||||
@PostMapping("/signin")
|
||||
@Operation(summary = "로그인", description = "사번 또는 이메일과 비밀번호로 로그인하여 액세스/리프레시 토큰을 발급합니다.")
|
||||
@Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "로그인 성공",
|
||||
content = @Content(schema = @Schema(implementation = TokenResponse.class))),
|
||||
responseCode = "200",
|
||||
description = "로그인 성공",
|
||||
content = @Content(schema = @Schema(implementation = TokenResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "401",
|
||||
description = "ID 또는 비밀번호 불일치",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
responseCode = "401",
|
||||
description = "ID 또는 비밀번호 불일치",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
})
|
||||
public ResponseEntity<TokenResponse> signin(
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
description = "로그인 요청 정보",
|
||||
required = true)
|
||||
@RequestBody
|
||||
SignInRequest request,
|
||||
HttpServletResponse response) {
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
description = "로그인 요청 정보",
|
||||
required = true)
|
||||
@RequestBody
|
||||
SignInRequest request,
|
||||
HttpServletResponse response) {
|
||||
Authentication authentication =
|
||||
authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(request.username(), request.password()));
|
||||
authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(request.username(), request.password()));
|
||||
|
||||
String username = authentication.getName(); // UserDetailsService 에서 사용한 username
|
||||
|
||||
@@ -70,17 +70,17 @@ public class AuthController {
|
||||
|
||||
// Redis에 RefreshToken 저장 (TTL = 7일)
|
||||
refreshTokenService.save(
|
||||
username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
|
||||
username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
|
||||
|
||||
// HttpOnly + Secure 쿠키에 RefreshToken 저장
|
||||
ResponseCookie cookie =
|
||||
ResponseCookie.from(refreshCookieName, refreshToken)
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure) // 로컬 개발에서 http만 쓰면 false 로 바꿔야 할 수도 있음
|
||||
.path("/")
|
||||
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
ResponseCookie.from(refreshCookieName, refreshToken)
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure)
|
||||
.path("/")
|
||||
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
|
||||
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||
|
||||
@@ -91,13 +91,13 @@ public class AuthController {
|
||||
@Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "재발급 성공",
|
||||
content = @Content(schema = @Schema(implementation = TokenResponse.class))),
|
||||
responseCode = "200",
|
||||
description = "재발급 성공",
|
||||
content = @Content(schema = @Schema(implementation = TokenResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "401",
|
||||
description = "만료되었거나 유효하지 않은 리프레시 토큰",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
responseCode = "401",
|
||||
description = "만료되었거나 유효하지 않은 리프레시 토큰",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
})
|
||||
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) {
|
||||
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
|
||||
@@ -117,29 +117,29 @@ public class AuthController {
|
||||
|
||||
// Redis 갱신
|
||||
refreshTokenService.save(
|
||||
username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
|
||||
username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
|
||||
|
||||
// 쿠키 갱신
|
||||
ResponseCookie cookie =
|
||||
ResponseCookie.from(refreshCookieName, newRefreshToken)
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure)
|
||||
.path("/")
|
||||
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
ResponseCookie.from(refreshCookieName, newRefreshToken)
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure)
|
||||
.path("/")
|
||||
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||
|
||||
return ResponseEntity.ok(new TokenResponse(newAccessToken));
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
@Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(블랙리스트 처리 또는 리프레시 토큰 삭제)합니다.")
|
||||
@Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "로그아웃 성공",
|
||||
content = @Content(schema = @Schema(implementation = Void.class)))
|
||||
responseCode = "200",
|
||||
description = "로그아웃 성공",
|
||||
content = @Content(schema = @Schema(implementation = Void.class)))
|
||||
})
|
||||
public ResponseEntity<Void> logout(Authentication authentication, HttpServletResponse response) {
|
||||
if (authentication != null) {
|
||||
@@ -150,13 +150,13 @@ public class AuthController {
|
||||
|
||||
// 쿠키 삭제 (Max-Age=0)
|
||||
ResponseCookie cookie =
|
||||
ResponseCookie.from(refreshCookieName, "")
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure)
|
||||
.path("/")
|
||||
.maxAge(0)
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
ResponseCookie.from(refreshCookieName, "")
|
||||
.httpOnly(true)
|
||||
.secure(refreshCookieSecure)
|
||||
.path("/")
|
||||
.maxAge(0)
|
||||
.sameSite("Strict")
|
||||
.build();
|
||||
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
@@ -164,8 +164,12 @@ public class AuthController {
|
||||
|
||||
@Schema(description = "로그인 요청 DTO")
|
||||
public record SignInRequest(
|
||||
@Schema(description = "사번", example = "11111") String username,
|
||||
@Schema(description = "비밀번호", example = "kamco1234!") String password) {}
|
||||
@Schema(description = "사번", example = "11111") String username,
|
||||
@Schema(description = "비밀번호", example = "kamco1234!") String password) {
|
||||
|
||||
public record TokenResponse(String accessToken) {}
|
||||
}
|
||||
|
||||
public record TokenResponse(String accessToken) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user