Skip to content

Commit

Permalink
Merge pull request #39 from 9oormthonUniv-seoultech/changha-dev
Browse files Browse the repository at this point in the history
SCRUM-32 HotFix : header -> json
  • Loading branch information
Changha-dev authored Nov 7, 2024
2 parents a4a50b3 + 9b103a3 commit 61005fa
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.groomiz.billage.auth.dto.LoginResponse;
import com.groomiz.billage.auth.dto.RefreshTokenRequest;
import com.groomiz.billage.auth.service.RefreshTokenService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;

@RestController
Expand All @@ -20,12 +21,12 @@ public class AuthController {
private final RefreshTokenService refreshTokenService;

@PostMapping("/refresh-token")
public ResponseEntity<?> reissue(HttpServletRequest request, HttpServletResponse response) {
public ResponseEntity<?> reissue(@RequestBody RefreshTokenRequest refreshTokenRequest) {
try {
return refreshTokenService.reissue(request, response);
LoginResponse reissue = refreshTokenService.reissue(refreshTokenRequest.getRefreshToken());
return ResponseEntity.ok(reissue);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Reissue failed: " + e.getMessage());
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.groomiz.billage.auth.document.StudentNumberExcptionDocs;
import com.groomiz.billage.auth.document.VerifyEmailException;
import com.groomiz.billage.auth.dto.LoginRequest;
import com.groomiz.billage.auth.dto.LoginResponse;
import com.groomiz.billage.auth.dto.RegisterRequest;
import com.groomiz.billage.auth.service.AuthService;
import com.groomiz.billage.auth.service.UnivCertService;
Expand Down Expand Up @@ -51,10 +52,9 @@ public class UserController {
@ApiErrorExceptionsExample(LoginExceptionDocs.class)
public ResponseEntity<?> login(@RequestBody @Valid LoginRequest loginRequest, HttpServletResponse response) {

authService.login(loginRequest, response);

return ResponseEntity.ok(new StringResponseDto("로그인 성공하였습니다."));
LoginResponse login = authService.login(loginRequest, response);

return ResponseEntity.ok(login);
}

@PostMapping("/logout")
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/groomiz/billage/auth/dto/LoginResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.groomiz.billage.auth.dto;


import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(description = "로그인 응답 DTO")
public class LoginResponse {

@Schema(description = "Access Token", example = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
private String authorization;

@Schema(description = "Refresh Token", example = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
private String refreshToken;

public LoginResponse(String authorization, String refreshToken) {
this.authorization = authorization;
this.refreshToken = refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.groomiz.billage.auth.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(description = "Refresh Token 요청 DTO")
public class RefreshTokenRequest {

@Schema(description = "Refresh Token", example = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
private String refreshToken;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.stereotype.Service;

import com.groomiz.billage.auth.dto.LoginRequest;
import com.groomiz.billage.auth.dto.LoginResponse;
import com.groomiz.billage.auth.exception.AuthErrorCode;
import com.groomiz.billage.auth.exception.AuthException;
import com.groomiz.billage.auth.jwt.JwtTokenProvider;
Expand All @@ -36,7 +37,7 @@ public class AuthService {
@Value("${spring.data.redis.cache.fcm-ttl}")
private Long fcmttl;

public void login(LoginRequest loginRequest, HttpServletResponse response) {
public LoginResponse login(LoginRequest loginRequest, HttpServletResponse response) {
try {
// 로그인 인증 처리
Authentication authentication = authenticate(loginRequest);
Expand All @@ -52,9 +53,8 @@ public void login(LoginRequest loginRequest, HttpServletResponse response) {
redisService.setValues(username, refreshToken, Duration.ofMillis(86400000L)); // 1일 유효
redisService.setValues("FCM_" + username, loginRequest.getFCMToken(), Duration.ofMillis(fcmttl)); // 30일 유효

// AccessToken과 RefreshToken을 헤더에 추가
response.setHeader("Authorization", "Bearer " + accessToken);
response.setHeader("RefreshToken", "Bearer " + refreshToken);
LoginResponse loginResponse = new LoginResponse("Bearer " + accessToken, "Bearer " + refreshToken);
return loginResponse;

} catch (BadCredentialsException e) {
// 비밀번호가 틀린 경우 AuthException 던지기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

import java.time.Duration;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.groomiz.billage.auth.dto.LoginResponse;
import com.groomiz.billage.auth.exception.AuthErrorCode;
import com.groomiz.billage.auth.exception.AuthException;
import com.groomiz.billage.auth.jwt.JwtUtil;

import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;

@Service
Expand All @@ -20,27 +19,29 @@ public class RefreshTokenService {
private final JwtUtil jwtUtil;
private final RedisService redisService;

public ResponseEntity<?> reissue(HttpServletRequest request, HttpServletResponse response) {
public LoginResponse reissue(String refreshToken) {

// 헤더에서 Bearer 형식의 RefreshToken 가져오기
String refreshToken = extractToken(request.getHeader("RefreshToken"));
if (refreshToken == null) {
return new ResponseEntity<>("Refresh token is null or not in the correct format", HttpStatus.BAD_REQUEST);
// RefreshToken이 존재하지 않거나 형식이 올바르지 않은 경우 예외 처리
if (refreshToken == null || !refreshToken.startsWith("Bearer ")) {
throw new AuthException(AuthErrorCode.TOKEN_NOT_FOUND);
}

// Bearer 부분 제거
refreshToken = refreshToken.substring(7);

// RefreshToken이 만료되었는지 확인
try {
jwtUtil.isExpired(refreshToken);
} catch (ExpiredJwtException e) {
return new ResponseEntity<>("Refresh token expired", HttpStatus.BAD_REQUEST);
throw new AuthException(AuthErrorCode.TOKEN_EXPIRED);
}

String studentNumber = jwtUtil.getStudentNumber(refreshToken);
String storedToken = redisService.getValues(studentNumber);

// Redis에 저장된 토큰과 비교하여 유효성 검증
if (!refreshToken.equals(storedToken)) {
return new ResponseEntity<>("Invalid refresh token", HttpStatus.BAD_REQUEST);
throw new AuthException(AuthErrorCode.INVALID_TOKEN);
}

// 새로운 AccessToken 및 RefreshToken 생성
Expand All @@ -52,18 +53,7 @@ public ResponseEntity<?> reissue(HttpServletRequest request, HttpServletResponse
redisService.deleteValues(studentNumber);
redisService.setValues(studentNumber, newRefreshToken, Duration.ofDays(1));

// 새로운 토큰을 헤더에 Bearer 형식으로 추가
response.setHeader("Authorization", "Bearer " + newAccessToken);
response.setHeader("RefreshToken", "Bearer " + newRefreshToken);

return new ResponseEntity<>(HttpStatus.OK);
}

// Bearer 토큰 형식에서 토큰만 추출하는 메서드
private String extractToken(String header) {
if (header != null && header.startsWith("Bearer ")) {
return header.substring(7);
}
return null;
// 새로운 AccessToken과 RefreshToken을 담은 LoginResponse 반환
return new LoginResponse("Bearer " + newAccessToken, "Bearer " + newRefreshToken);
}
}

0 comments on commit 61005fa

Please sign in to comment.