diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index fdc392f..02bd16d 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -16,5 +16,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 35e923a..ffc0704 100644
--- a/build.gradle
+++ b/build.gradle
@@ -108,6 +108,9 @@ dependencies {
//s3
implementation 'io.awspring.cloud:spring-cloud-aws-starter:3.1.1'
implementation 'software.amazon.awssdk:s3:2.20.40'
+
+ // oauth
+ implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
tasks.named('test') {
diff --git a/src/main/java/kdt/web_ide/boards/controller/BoardController.java b/src/main/java/kdt/web_ide/boards/controller/BoardController.java
index 7365841..7f956fe 100644
--- a/src/main/java/kdt/web_ide/boards/controller/BoardController.java
+++ b/src/main/java/kdt/web_ide/boards/controller/BoardController.java
@@ -13,7 +13,6 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import kdt.web_ide.boards.dto.request.BoardSaveRequesetDto;
import kdt.web_ide.boards.dto.request.BoardUpdateRequestDto;
-import kdt.web_ide.boards.dto.request.BoardUserInviteRequestDto;
import kdt.web_ide.boards.dto.response.BoardResponseDto;
import kdt.web_ide.boards.dto.response.BoardUserResponseDto;
import kdt.web_ide.boards.service.BoardService;
@@ -58,17 +57,17 @@ public ResponseEntity deleteBoard(
return ResponseEntity.status(HttpStatus.OK).body("게시판이 삭제되었습니다.");
}
- // 게시판 인원 초대
- @Operation(summary = "게시판 멤버 초대 API", description = "이메일로 멤버를 초대합니다. 리더만 초대 가능합니다.")
- @PostMapping("/{boardId}/invite")
- public ResponseEntity inviteMember(
- @PathVariable Long boardId,
- @RequestBody @Valid BoardUserInviteRequestDto requestDto,
- @AuthenticationPrincipal CustomUserDetails userDetails) {
- BoardUserResponseDto invitedUser =
- boardService.inviteMember(requestDto, boardId, userDetails.getMember());
- return ResponseEntity.ok(invitedUser);
- }
+ // // 게시판 인원 초대
+ // @Operation(summary = "게시판 멤버 초대 API", description = "이메일로 멤버를 초대합니다. 리더만 초대 가능합니다.")
+ // @PostMapping("/{boardId}/invite")
+ // public ResponseEntity inviteMember(
+ // @PathVariable Long boardId,
+ // @RequestBody @Valid BoardUserInviteRequestDto requestDto,
+ // @AuthenticationPrincipal CustomUserDetails userDetails) {
+ // BoardUserResponseDto invitedUser =
+ // boardService.inviteMember(requestDto, boardId, userDetails.getMember());
+ // return ResponseEntity.ok(invitedUser);
+ // }
// 게시판 인원 조회
@Operation(summary = "게시판 인원 조회 API", description = "해당 게시판의 모든 멤버를 조회합니다.")
diff --git a/src/main/java/kdt/web_ide/boards/service/BoardService.java b/src/main/java/kdt/web_ide/boards/service/BoardService.java
index 2240c8a..31e6360 100644
--- a/src/main/java/kdt/web_ide/boards/service/BoardService.java
+++ b/src/main/java/kdt/web_ide/boards/service/BoardService.java
@@ -9,7 +9,6 @@
import kdt.web_ide.boards.dto.request.BoardSaveRequesetDto;
import kdt.web_ide.boards.dto.request.BoardUpdateRequestDto;
-import kdt.web_ide.boards.dto.request.BoardUserInviteRequestDto;
import kdt.web_ide.boards.dto.response.BoardResponseDto;
import kdt.web_ide.boards.dto.response.BoardUserResponseDto;
import kdt.web_ide.boards.entity.Board;
@@ -74,26 +73,26 @@ public void deleteBoard(Long boardId, Member member) {
}
// 게시판 인원 초대
- @Transactional
- public BoardUserResponseDto inviteMember(
- BoardUserInviteRequestDto requestDto, Long boardId, Member currentMember) {
- if (requestDto.getLoginId() == null || requestDto.getLoginId().isEmpty()) {
- throw new CustomException(ErrorCode.INVALID_LOGINID);
- }
- // 존재하는 게시판인지 확인
- Board thisBoard =
- boardRepository
- .findById(boardId)
- .orElseThrow(() -> new CustomException(ErrorCode.BOARD_NOT_FOUND));
- // 존재하는 멤버인지 확인
- Member member =
- memberRepository
- .findByLoginId(requestDto.getLoginId())
- .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
- BoardUser newUser = requestDto.toEntity(thisBoard, member);
- boardUserRepository.save(newUser);
- return new BoardUserResponseDto(newUser);
- }
+ // @Transactional
+ // public BoardUserResponseDto inviteMember(
+ // BoardUserInviteRequestDto requestDto, Long boardId, Member currentMember) {
+ // if (requestDto.getLoginId() == null || requestDto.getLoginId().isEmpty()) {
+ // throw new CustomException(ErrorCode.INVALID_LOGINID);
+ // }
+ // // 존재하는 게시판인지 확인
+ // Board thisBoard =
+ // boardRepository
+ // .findById(boardId)
+ // .orElseThrow(() -> new CustomException(ErrorCode.BOARD_NOT_FOUND));
+ // // 존재하는 멤버인지 확인
+ // Member member =
+ // memberRepository
+ // .findByLoginId(requestDto.getLoginId())
+ // .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
+ // BoardUser newUser = requestDto.toEntity(thisBoard, member);
+ // boardUserRepository.save(newUser);
+ // return new BoardUserResponseDto(newUser);
+ // }
// 게시판 인원 조회
@Transactional
diff --git a/src/main/java/kdt/web_ide/common/config/RestTemplateConfig.java b/src/main/java/kdt/web_ide/common/config/RestTemplateConfig.java
new file mode 100644
index 0000000..2de00b9
--- /dev/null
+++ b/src/main/java/kdt/web_ide/common/config/RestTemplateConfig.java
@@ -0,0 +1,14 @@
+package kdt.web_ide.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig {
+
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+}
diff --git a/src/main/java/kdt/web_ide/common/config/WebSecurityConfig.java b/src/main/java/kdt/web_ide/common/config/WebSecurityConfig.java
index 083250a..43f4379 100644
--- a/src/main/java/kdt/web_ide/common/config/WebSecurityConfig.java
+++ b/src/main/java/kdt/web_ide/common/config/WebSecurityConfig.java
@@ -7,8 +7,6 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
@@ -32,12 +30,6 @@ public class WebSecurityConfig {
private final JwtExceptionFilter jwtExceptionFilter;
private final CustomAccessDeniedHandler customAccessDeniedHandler;
- // 비밀번호 암호화 방식 설정
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
-
// 보안 설정
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
@@ -62,7 +54,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
"/v3/api-docs/**",
"/swagger-resources/**",
"/webjars/**",
- "/health")
+ "/health",
+ "/kakao/**",
+ "/api/auth/login")
.permitAll()
.requestMatchers("/api/auth/**", "/chatting/**", "/api/chat/room")
.permitAll()
diff --git a/src/main/java/kdt/web_ide/members/controller/MemberController.java b/src/main/java/kdt/web_ide/members/controller/MemberController.java
index e1a648b..13957e6 100644
--- a/src/main/java/kdt/web_ide/members/controller/MemberController.java
+++ b/src/main/java/kdt/web_ide/members/controller/MemberController.java
@@ -11,12 +11,10 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
-import kdt.web_ide.members.dto.request.JoinRequestDto;
-import kdt.web_ide.members.dto.request.LoginRequestDto;
-import kdt.web_ide.members.dto.request.RefreshTokenRequestDto;
-import kdt.web_ide.members.dto.response.AccessTokenResponseDto;
-import kdt.web_ide.members.dto.response.LoginResponseDto;
import kdt.web_ide.members.dto.response.MemberResponse;
+import kdt.web_ide.members.dto.response.TokenResponse;
+import kdt.web_ide.members.kakao.KakaoLoginParams;
+import kdt.web_ide.members.kakao.KakaoReissueParams;
import kdt.web_ide.members.service.CustomUserDetails;
import kdt.web_ide.members.service.MemberService;
import lombok.RequiredArgsConstructor;
@@ -29,18 +27,10 @@ public class MemberController {
private final MemberService memberService;
- // 회원가입
- @PostMapping("/join")
- public ResponseEntity> join(@RequestBody JoinRequestDto joinRequestDto) {
- MemberResponse responseDto = memberService.signUp(joinRequestDto);
- return ResponseEntity.status(HttpStatus.OK).body(responseDto);
- }
-
// 로그인
@PostMapping("/login")
- public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto) {
- LoginResponseDto memberResponse = memberService.login(loginRequestDto);
- return ResponseEntity.status(HttpStatus.OK).body(memberResponse);
+ public ResponseEntity> login(@RequestBody KakaoLoginParams params) {
+ return ResponseEntity.status(HttpStatus.OK).body(memberService.login(params));
}
// 회원 정보 조회
@@ -73,21 +63,9 @@ public ResponseEntity updateNickName(
return ResponseEntity.status(HttpStatus.OK).body(updatedMember);
}
- @Operation(summary = "로그인 아이디 수정 API")
- @PatchMapping("/profile/login-id")
- public ResponseEntity updateLoginId(
- @RequestParam("loginId") String newLoginId,
- @AuthenticationPrincipal CustomUserDetails userDetails) {
- MemberResponse updatedMember = memberService.updateLoginId(newLoginId, userDetails.getMember());
- return ResponseEntity.ok(updatedMember);
- }
-
@Operation(summary = "엑세스 토큰 재발급 API")
@PostMapping("/refresh")
- public ResponseEntity recreateAccessToken(
- @RequestBody RefreshTokenRequestDto requestDto) {
- String accessToken = memberService.validateRefreshToken(requestDto.getRefreshToken());
- AccessTokenResponseDto responseDto = new AccessTokenResponseDto(accessToken);
- return ResponseEntity.status(HttpStatus.OK).body(responseDto);
+ public ResponseEntity recreateAccessToken(@RequestBody KakaoReissueParams params) {
+ return ResponseEntity.status(HttpStatus.OK).body(memberService.reissue(params));
}
}
diff --git a/src/main/java/kdt/web_ide/members/dto/request/CustomUserInfoDto.java b/src/main/java/kdt/web_ide/members/dto/request/CustomUserInfoDto.java
deleted file mode 100644
index 4e5ad85..0000000
--- a/src/main/java/kdt/web_ide/members/dto/request/CustomUserInfoDto.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package kdt.web_ide.members.dto.request;
-
-import java.util.List;
-
-import kdt.web_ide.members.entity.RoleType;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Getter
-@NoArgsConstructor
-@AllArgsConstructor
-public class CustomUserInfoDto {
- Long memberId;
- String loginId;
- List roles; // 역할을 리스트로 변경
-}
diff --git a/src/main/java/kdt/web_ide/members/dto/request/JoinRequestDto.java b/src/main/java/kdt/web_ide/members/dto/request/JoinRequestDto.java
deleted file mode 100644
index d95c3c8..0000000
--- a/src/main/java/kdt/web_ide/members/dto/request/JoinRequestDto.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package kdt.web_ide.members.dto.request;
-
-import java.util.Collections;
-
-import jakarta.validation.constraints.Pattern;
-
-import kdt.web_ide.members.entity.Member;
-import kdt.web_ide.members.entity.RoleType;
-import lombok.*;
-
-@Getter
-@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
-public class JoinRequestDto {
-
- private final String loginId;
-
- @Pattern(
- regexp = "^[a-zA-Z0-9가-힣]{2,10}$",
- message = "닉네임은 최소 2자 이상, 10자 이하이며, 영문, 숫자, 한글만 입력하세요.")
- private final String nickName;
-
- @Pattern(
- regexp = "(?=.*[a-zA-Z])(?=.*[0-9])^[a-zA-Z0-9~!@#$%^&*()+|=]{8}$",
- message = "비밀번호는 8자, 소문자와 숫자만 입력하세요.")
- private final String password;
-
- @Pattern(
- regexp = "(?=.*[a-zA-Z])(?=.*[0-9])^[a-zA-Z0-9~!@#$%^&*()+|=]{8}$",
- message = "비밀번호를 확인해주세요.")
- private final String password2;
-
- @Builder
- public JoinRequestDto(String loginId, String nickName, String password, String password2) {
- this.loginId = loginId;
- this.nickName = nickName;
- this.password = password;
- this.password2 = password2;
- }
-
- public Member toEntity(RoleType role, String encodedPassword) {
- return Member.builder()
- .loginId(loginId)
- .password(encodedPassword)
- .nickName(nickName)
- .roles(Collections.singletonList(role))
- .build();
- }
-}
diff --git a/src/main/java/kdt/web_ide/members/dto/request/LoginRequestDto.java b/src/main/java/kdt/web_ide/members/dto/request/LoginRequestDto.java
deleted file mode 100644
index 2bffb38..0000000
--- a/src/main/java/kdt/web_ide/members/dto/request/LoginRequestDto.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package kdt.web_ide.members.dto.request;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor
-@AllArgsConstructor
-@Getter
-public class LoginRequestDto {
- String loginId;
- String password;
-}
diff --git a/src/main/java/kdt/web_ide/members/dto/request/RefreshTokenRequestDto.java b/src/main/java/kdt/web_ide/members/dto/request/RefreshTokenRequestDto.java
deleted file mode 100644
index 9f7f0cf..0000000
--- a/src/main/java/kdt/web_ide/members/dto/request/RefreshTokenRequestDto.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package kdt.web_ide.members.dto.request;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor
-@Getter
-public class RefreshTokenRequestDto {
-
- private String refreshToken;
-}
diff --git a/src/main/java/kdt/web_ide/members/dto/response/LoginResponseDto.java b/src/main/java/kdt/web_ide/members/dto/response/LoginResponseDto.java
index 81b10ba..ac12746 100644
--- a/src/main/java/kdt/web_ide/members/dto/response/LoginResponseDto.java
+++ b/src/main/java/kdt/web_ide/members/dto/response/LoginResponseDto.java
@@ -11,14 +11,14 @@ public class LoginResponseDto {
private Long memberId;
private String nickName;
- private String loginId;
+ private String profileImage;
private TokenResponse tokenResponse;
@Builder
public LoginResponseDto(Member member, TokenResponse tokenResponse) {
this.memberId = member.getMemberId();
this.nickName = member.getNickName();
- this.loginId = member.getLoginId();
+ this.profileImage = member.getProfileImage();
this.tokenResponse = tokenResponse;
}
}
diff --git a/src/main/java/kdt/web_ide/members/dto/response/MemberResponse.java b/src/main/java/kdt/web_ide/members/dto/response/MemberResponse.java
index e67b86b..b1624c4 100644
--- a/src/main/java/kdt/web_ide/members/dto/response/MemberResponse.java
+++ b/src/main/java/kdt/web_ide/members/dto/response/MemberResponse.java
@@ -9,14 +9,12 @@
public class MemberResponse {
public MemberResponse(Member member) {
this.memberId = member.getMemberId();
- this.loginId = member.getLoginId();
this.nickName = member.getNickName();
this.profileImage = member.getProfileImage();
}
private final Long memberId;
- private final String loginId;
private final String nickName;
private final String profileImage;
diff --git a/src/main/java/kdt/web_ide/members/dto/response/TokenResponse.java b/src/main/java/kdt/web_ide/members/dto/response/TokenResponse.java
index 103a121..eccee13 100644
--- a/src/main/java/kdt/web_ide/members/dto/response/TokenResponse.java
+++ b/src/main/java/kdt/web_ide/members/dto/response/TokenResponse.java
@@ -8,6 +8,4 @@
public class TokenResponse {
String accessToken;
String refreshToken;
-
- String key;
}
diff --git a/src/main/java/kdt/web_ide/members/entity/Member.java b/src/main/java/kdt/web_ide/members/entity/Member.java
index bbc7e9d..af8b232 100644
--- a/src/main/java/kdt/web_ide/members/entity/Member.java
+++ b/src/main/java/kdt/web_ide/members/entity/Member.java
@@ -5,8 +5,6 @@
import jakarta.persistence.*;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
import kdt.web_ide.BaseTimeEntity;
import lombok.*;
@@ -21,35 +19,26 @@ public class Member extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long memberId;
- @Column(nullable = false, unique = true)
- private String nickName;
+ @Column(name = "kakao_id")
+ private Long kakaoId;
+ @Setter
@Column(nullable = false, unique = true)
- private String loginId;
-
- private String password;
+ private String nickName;
+ @Setter
@Column(name = "profile_img")
private String profileImage;
- public void encodePassword(PasswordEncoder passwordEncoder) {
- this.password = passwordEncoder.encode(password);
- }
+ @Setter
+ @Column(name = "refresh_token")
+ private String refreshToken;
+
+ @Column(name = "identification_code")
+ private String identificationCode;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "member_roles", joinColumns = @JoinColumn(name = "member_id"))
@Enumerated(EnumType.STRING)
private List roles = new ArrayList<>();
-
- public void updateImage(String profileImage) {
- this.profileImage = profileImage;
- }
-
- public void updateNickName(String nickName) {
- this.nickName = nickName;
- }
-
- public void updateLoginId(String loginId) {
- this.loginId = loginId;
- }
}
diff --git a/src/main/java/kdt/web_ide/members/entity/RefreshToken.java b/src/main/java/kdt/web_ide/members/entity/RefreshToken.java
deleted file mode 100644
index b366473..0000000
--- a/src/main/java/kdt/web_ide/members/entity/RefreshToken.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package kdt.web_ide.members.entity;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-
-import kdt.web_ide.BaseTimeEntity;
-import lombok.*;
-
-@Builder
-@Entity
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class RefreshToken extends BaseTimeEntity {
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private String refreshToken;
-
- private String keyUserId;
-}
diff --git a/src/main/java/kdt/web_ide/members/entity/repository/MemberRepository.java b/src/main/java/kdt/web_ide/members/entity/repository/MemberRepository.java
index a79f05f..30a2de3 100644
--- a/src/main/java/kdt/web_ide/members/entity/repository/MemberRepository.java
+++ b/src/main/java/kdt/web_ide/members/entity/repository/MemberRepository.java
@@ -10,9 +10,9 @@
public interface MemberRepository extends JpaRepository {
- Optional findByNickName(String nickName);
+ Optional findByKakaoId(Long kakaoId);
- Optional findByLoginId(String userId);
+ Optional findByNickName(String nickName);
@Query("""
Select br.member
diff --git a/src/main/java/kdt/web_ide/members/entity/repository/RefreshTokenRepository.java b/src/main/java/kdt/web_ide/members/entity/repository/RefreshTokenRepository.java
deleted file mode 100644
index 7a7d6f0..0000000
--- a/src/main/java/kdt/web_ide/members/entity/repository/RefreshTokenRepository.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package kdt.web_ide.members.entity.repository;
-
-import java.util.Optional;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import kdt.web_ide.members.entity.RefreshToken;
-
-public interface RefreshTokenRepository extends JpaRepository {
- Optional findByRefreshToken(String refreshToken);
-
- boolean existsByKeyUserId(String userId);
-
- void deleteByKeyUserId(String userId);
-}
diff --git a/src/main/java/kdt/web_ide/members/kakao/KakaoApiClient.java b/src/main/java/kdt/web_ide/members/kakao/KakaoApiClient.java
new file mode 100644
index 0000000..d6ac3e6
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/kakao/KakaoApiClient.java
@@ -0,0 +1,96 @@
+package kdt.web_ide.members.kakao;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import kdt.web_ide.members.oAuth.OAuthApiClient;
+import kdt.web_ide.members.oAuth.OAuthInfoResponse;
+import kdt.web_ide.members.oAuth.OAuthLoginParams;
+import lombok.RequiredArgsConstructor;
+
+@Component
+@RequiredArgsConstructor
+public class KakaoApiClient implements OAuthApiClient {
+
+ private static final String GRANT_TYPE = "authorization_code";
+
+ @Value("${oauth.kakao.url.auth}")
+ private String authUrl;
+
+ @Value("${oauth.kakao.url.api}")
+ private String apiUrl;
+
+ @Value("${oauth.kakao.client-id}")
+ private String clientId;
+
+ @Value("${oauth.kakao.client-secret}")
+ private String clientSecret;
+
+ private final RestTemplate restTemplate;
+
+ @Override
+ public String requestAccessToken(OAuthLoginParams params) {
+
+ String url = authUrl + "/oauth/token";
+
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(
+ MediaType.valueOf("application/x-www-form-urlencoded;charset=utf-8"));
+
+ MultiValueMap body = params.makeBody();
+ body.add("grant_type", GRANT_TYPE);
+ body.add("client_id", clientId);
+ body.add("client_secret", clientSecret);
+
+ HttpEntity> request = new HttpEntity<>(body, httpHeaders);
+
+ KakaoToken response = restTemplate.postForObject(url, request, KakaoToken.class);
+
+ assert response != null;
+
+ return response.getAccessToken();
+ }
+
+ @Override
+ public OAuthInfoResponse requestOauthInfo(String accessToken) {
+ String url = apiUrl + "/v2/user/me";
+
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+ httpHeaders.set("Authorization", "Bearer " + accessToken);
+
+ MultiValueMap body = new LinkedMultiValueMap<>();
+ body.add("property_keys", "[\"kakao_account.profile\"]");
+
+ HttpEntity> request = new HttpEntity<>(body, httpHeaders);
+
+ return restTemplate.postForObject(url, request, KakaoInfoResponse.class);
+ }
+
+ @Override
+ public String reissueAccessToken(KakaoReissueParams params) {
+ String url = authUrl + "/oauth/token";
+
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+ MultiValueMap body = params.makeBody();
+ body.add("grant_type", GRANT_TYPE);
+ body.add("client_id", clientId);
+ body.add("client_secret", clientSecret);
+
+ HttpEntity> request = new HttpEntity<>(body, httpHeaders);
+
+ KakaoToken response = restTemplate.postForObject(url, request, KakaoToken.class);
+
+ assert response != null;
+
+ return response.getAccessToken();
+ }
+}
diff --git a/src/main/java/kdt/web_ide/members/kakao/KakaoInfoResponse.java b/src/main/java/kdt/web_ide/members/kakao/KakaoInfoResponse.java
new file mode 100644
index 0000000..538a24e
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/kakao/KakaoInfoResponse.java
@@ -0,0 +1,41 @@
+package kdt.web_ide.members.kakao;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import kdt.web_ide.members.oAuth.OAuthInfoResponse;
+import lombok.Getter;
+
+@Getter
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class KakaoInfoResponse implements OAuthInfoResponse {
+
+ @JsonProperty("id")
+ private Long kakaoId;
+
+ @JsonProperty("kakao_account")
+ private KakaoAccount kakaoAccount;
+
+ @Getter
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ static class KakaoAccount {
+ private KakaoProfile profile;
+ }
+
+ @Getter
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ static class KakaoProfile {
+ private String nickname;
+ private String profile_image_url;
+ }
+
+ @Override
+ public String getKakaoNickname() {
+ return kakaoAccount.profile.nickname;
+ }
+
+ @Override
+ public String getKakaoProfileImage() {
+ return kakaoAccount.profile.profile_image_url;
+ }
+}
diff --git a/src/main/java/kdt/web_ide/members/kakao/KakaoLoginParams.java b/src/main/java/kdt/web_ide/members/kakao/KakaoLoginParams.java
new file mode 100644
index 0000000..4827fdb
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/kakao/KakaoLoginParams.java
@@ -0,0 +1,22 @@
+package kdt.web_ide.members.kakao;
+
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import kdt.web_ide.members.oAuth.OAuthLoginParams;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@NoArgsConstructor
+public class KakaoLoginParams implements OAuthLoginParams {
+
+ private String authorizationCode;
+
+ @Override
+ public MultiValueMap makeBody() {
+ MultiValueMap body = new LinkedMultiValueMap<>();
+ body.add("code", authorizationCode);
+ return body;
+ }
+}
diff --git a/src/main/java/kdt/web_ide/members/kakao/KakaoReissueParams.java b/src/main/java/kdt/web_ide/members/kakao/KakaoReissueParams.java
new file mode 100644
index 0000000..071f808
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/kakao/KakaoReissueParams.java
@@ -0,0 +1,20 @@
+package kdt.web_ide.members.kakao;
+
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@NoArgsConstructor
+public class KakaoReissueParams {
+
+ private String refreshToken;
+
+ public MultiValueMap makeBody() {
+ MultiValueMap body = new LinkedMultiValueMap<>();
+ body.add("refresh_token", refreshToken);
+ return body;
+ }
+}
diff --git a/src/main/java/kdt/web_ide/members/kakao/KakaoToken.java b/src/main/java/kdt/web_ide/members/kakao/KakaoToken.java
new file mode 100644
index 0000000..3277b3f
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/kakao/KakaoToken.java
@@ -0,0 +1,29 @@
+package kdt.web_ide.members.kakao;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@NoArgsConstructor
+public class KakaoToken {
+
+ @JsonProperty("access_token")
+ private String accessToken;
+
+ @JsonProperty("token_type")
+ private String tokenType;
+
+ @JsonProperty("refresh_token")
+ private String refreshToken;
+
+ @JsonProperty("expires_in")
+ private String expiresIn;
+
+ @JsonProperty("refresh_token_expires_in")
+ private String refreshTokenExpiresIn;
+
+ @JsonProperty("scope")
+ private String scope;
+}
diff --git a/src/main/java/kdt/web_ide/members/oAuth/OAuthApiClient.java b/src/main/java/kdt/web_ide/members/oAuth/OAuthApiClient.java
new file mode 100644
index 0000000..bdc2f22
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/oAuth/OAuthApiClient.java
@@ -0,0 +1,12 @@
+package kdt.web_ide.members.oAuth;
+
+import kdt.web_ide.members.kakao.KakaoReissueParams;
+
+public interface OAuthApiClient {
+
+ String requestAccessToken(OAuthLoginParams params);
+
+ String reissueAccessToken(KakaoReissueParams params);
+
+ OAuthInfoResponse requestOauthInfo(String accessToken);
+}
diff --git a/src/main/java/kdt/web_ide/members/oAuth/OAuthInfoResponse.java b/src/main/java/kdt/web_ide/members/oAuth/OAuthInfoResponse.java
new file mode 100644
index 0000000..50d0d1c
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/oAuth/OAuthInfoResponse.java
@@ -0,0 +1,9 @@
+package kdt.web_ide.members.oAuth;
+
+public interface OAuthInfoResponse {
+ Long getKakaoId();
+
+ String getKakaoNickname();
+
+ String getKakaoProfileImage();
+}
diff --git a/src/main/java/kdt/web_ide/members/oAuth/OAuthLoginParams.java b/src/main/java/kdt/web_ide/members/oAuth/OAuthLoginParams.java
new file mode 100644
index 0000000..195dd6f
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/oAuth/OAuthLoginParams.java
@@ -0,0 +1,7 @@
+package kdt.web_ide.members.oAuth;
+
+import org.springframework.util.MultiValueMap;
+
+public interface OAuthLoginParams {
+ MultiValueMap makeBody();
+}
diff --git a/src/main/java/kdt/web_ide/members/oAuth/RequestOAuthInfoService.java b/src/main/java/kdt/web_ide/members/oAuth/RequestOAuthInfoService.java
new file mode 100644
index 0000000..a6e2dad
--- /dev/null
+++ b/src/main/java/kdt/web_ide/members/oAuth/RequestOAuthInfoService.java
@@ -0,0 +1,25 @@
+package kdt.web_ide.members.oAuth;
+
+import org.springframework.stereotype.Component;
+
+import kdt.web_ide.members.kakao.KakaoReissueParams;
+
+@Component
+public class RequestOAuthInfoService {
+
+ private final OAuthApiClient client;
+
+ public RequestOAuthInfoService(OAuthApiClient client) {
+ this.client = client;
+ }
+
+ public OAuthInfoResponse request(OAuthLoginParams params) {
+ String accessToken = client.requestAccessToken(params);
+ return client.requestOauthInfo(accessToken);
+ }
+
+ public OAuthInfoResponse reissue(KakaoReissueParams params) {
+ String accessToken = client.reissueAccessToken(params);
+ return client.requestOauthInfo(accessToken);
+ }
+}
diff --git a/src/main/java/kdt/web_ide/members/service/CustomUserDetailService.java b/src/main/java/kdt/web_ide/members/service/CustomUserDetailService.java
index a47aed8..2504eaf 100644
--- a/src/main/java/kdt/web_ide/members/service/CustomUserDetailService.java
+++ b/src/main/java/kdt/web_ide/members/service/CustomUserDetailService.java
@@ -23,7 +23,7 @@ public UserDetails loadUserByUsername(String userId) {
log.info("User Name = {}", userId);
Member member =
memberRepository
- .findByLoginId(userId)
+ .findById(Long.parseLong(userId))
.orElseThrow(
() -> {
log.error("사용자를 찾을 수 없습니다: {}", userId);
diff --git a/src/main/java/kdt/web_ide/members/service/JwtProvider.java b/src/main/java/kdt/web_ide/members/service/JwtProvider.java
index 4a6ff85..d148e85 100644
--- a/src/main/java/kdt/web_ide/members/service/JwtProvider.java
+++ b/src/main/java/kdt/web_ide/members/service/JwtProvider.java
@@ -14,9 +14,8 @@
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
-import kdt.web_ide.members.dto.request.CustomUserInfoDto;
-import kdt.web_ide.members.dto.response.TokenResponse;
-import kdt.web_ide.members.entity.RefreshToken;
+import kdt.web_ide.common.exception.CustomException;
+import kdt.web_ide.common.exception.ErrorCode;
import kdt.web_ide.members.entity.RoleType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -61,22 +60,19 @@ public String resolveToken(HttpServletRequest request) {
}
/**
- * 엑세스 토큰 생성
+ * 토큰 생성
*
- * @param member
* @param expireTime
* @return
*/
- public String createToken(RoleType role, CustomUserInfoDto member, Long expireTime) {
+ private String createToken(RoleType role, Long memberId, Long expireTime) {
Claims claims = Jwts.claims();
- claims.put("memberId", member.getMemberId());
- claims.put("loginId", member.getLoginId());
- claims.put("role", member.getRoles());
+ claims.put("memberId", memberId);
+ claims.put("role", RoleType.USER);
Date now = new Date();
return Jwts.builder()
.claim(AUTHORIZATION_KEY, role)
- .setSubject(member.getLoginId())
.setClaims(claims)
.setExpiration(new Date(now.getTime() + expireTime))
.setIssuedAt(now)
@@ -85,29 +81,23 @@ public String createToken(RoleType role, CustomUserInfoDto member, Long expireTi
}
/**
- * 토큰 재생성
+ * 액세스 토큰 생성
*
- * @param role
- * @param member
- * @param expireTime
+ * @param memberId
* @return
*/
- public String recreateAccessToken(RoleType role, CustomUserInfoDto member, Long expireTime) {
- Claims claims = Jwts.claims();
- claims.put("memberId", member.getMemberId());
- claims.put("loginId", member.getLoginId());
- claims.put("role", member.getRoles());
-
- Date now = new Date();
+ public String generateAccessToken(Long memberId) {
+ return createToken(RoleType.USER, memberId, TOKEN_TIME);
+ }
- return Jwts.builder()
- .claim(AUTHORIZATION_KEY, role)
- .setSubject(member.getLoginId())
- .setClaims(claims)
- .setExpiration(new Date(now.getTime() + expireTime))
- .setIssuedAt(now)
- .signWith(SignatureAlgorithm.HS256, key)
- .compact();
+ /**
+ * 리프레시 토큰 생성
+ *
+ * @param memberId
+ * @return
+ */
+ public String generateRefreshToken(Long memberId) {
+ return createToken(RoleType.USER, memberId, REFRESH_TOKEN_TIME);
}
/**
@@ -146,113 +136,19 @@ public boolean validateToken(String jwtToken) {
/**
* 유저 정보 저장
*
- * @param loginId
+ * @param memberId
* @return
*/
- public UsernamePasswordAuthenticationToken createUserAuthentication(String loginId) {
- UserDetails userDetails = customUserDetailsService.loadUserByUsername(loginId);
+ public UsernamePasswordAuthenticationToken createUserAuthentication(String memberId) {
+ UserDetails userDetails = customUserDetailsService.loadUserByUsername(memberId);
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
- /**
- * 로그인 시 토큰 생성
- *
- * @param member
- * @return
- */
- public TokenResponse createTokenByLogin(CustomUserInfoDto member) {
- String accessToken = createToken(RoleType.USER, member, TOKEN_TIME);
- String refreshToken = createToken(RoleType.USER, member, REFRESH_TOKEN_TIME);
- return new TokenResponse(accessToken, refreshToken, member.getLoginId());
- }
-
- /**
- * 토큰 무효화 (블랙리스트에 추가)
- *
- * @param token
- */
- public void invalidateToken(String token, String loginId) {
+ public Long parseRefreshToken(String token) {
if (validateToken(token)) {
- blacklistedTokens.add(token);
- log.info("Token invalidated: {}", token);
- } else {
- log.warn("Invalid token: {}", token);
- }
- }
-
- /**
- * 토큰이 블랙리스트에 있는지 확인
- *
- * @param token
- * @return
- */
- public boolean isTokenBlacklisted(String token) {
- return blacklistedTokens.contains(token);
- }
-
- /**
- * 토큰 만료시간 조회
- *
- * @param accessToken
- * @return
- */
- public Long getExpiration(String accessToken) {
- // 엑세스 토큰 만료시간
- Date expiration =
- Jwts.parserBuilder()
- .setSigningKey(key)
- .build()
- .parseClaimsJws(accessToken)
- .getBody()
- .getExpiration();
- // 현재시간
- long now = new Date().getTime();
- return (expiration.getTime() - now);
- }
-
- /**
- * 리프레시 토큰의 유효성 및 만료 여부 확인
- *
- * @param refreshTokenObj 리프레시 토큰 객체
- * @return 새로 생성된 액세스 토큰 (유효하면), 만료 시 예외 발생
- */
- public String validateRefreshToken(RefreshToken refreshTokenObj) {
- // refresh 객체에서 refreshToken 추출
- String refreshToken = refreshTokenObj.getRefreshToken();
- if (refreshToken.startsWith("Bearer ")) {
- refreshToken = refreshToken.substring(7);
- }
-
- try {
- Jws claims =
- Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(refreshToken);
-
- Date expiration = claims.getBody().getExpiration();
- Date now = new Date();
-
- // 만료 여부 확인
- if (expiration.before(now)) {
- log.warn("리프레시 토큰이 만료되었습니다.");
- return null;
- }
-
- // 로그인 ID, 역할 정보 추출
- Long memberId = claims.getBody().get("memberId", Long.class);
- String loginId = claims.getBody().get("loginId", String.class);
- List roles = claims.getBody().get("role", List.class);
-
- if (memberId == null || loginId == null || roles == null) {
- log.error("JWT에서 memberId, loginId 또는 roles 값을 찾을 수 없습니다!");
- return null;
- }
- CustomUserInfoDto userInfo = new CustomUserInfoDto(memberId, loginId, roles);
- return recreateAccessToken(RoleType.USER, userInfo, TOKEN_TIME);
- } catch (ExpiredJwtException e) {
- log.warn("JWT Expired: {}", e.getMessage());
- return null;
- } catch (JwtException e) {
- log.error("Invalid Token: {}", e.getMessage());
- return null;
+ Claims claims = getUserInfoFromToken(token);
+ return Long.parseLong(claims.getSubject());
}
+ throw new CustomException(ErrorCode.USER_NOT_FOUND);
}
}
diff --git a/src/main/java/kdt/web_ide/members/service/MemberService.java b/src/main/java/kdt/web_ide/members/service/MemberService.java
index 86f5531..1ab987b 100644
--- a/src/main/java/kdt/web_ide/members/service/MemberService.java
+++ b/src/main/java/kdt/web_ide/members/service/MemberService.java
@@ -3,124 +3,100 @@
import java.io.IOException;
import jakarta.transaction.Transactional;
-import jakarta.validation.Valid;
-import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import kdt.web_ide.common.exception.CustomException;
import kdt.web_ide.common.exception.ErrorCode;
-import kdt.web_ide.members.dto.request.CustomUserInfoDto;
-import kdt.web_ide.members.dto.request.JoinRequestDto;
-import kdt.web_ide.members.dto.request.LoginRequestDto;
import kdt.web_ide.members.dto.response.LoginResponseDto;
import kdt.web_ide.members.dto.response.MemberResponse;
import kdt.web_ide.members.dto.response.TokenResponse;
import kdt.web_ide.members.entity.Member;
-import kdt.web_ide.members.entity.RefreshToken;
-import kdt.web_ide.members.entity.RoleType;
import kdt.web_ide.members.entity.repository.MemberRepository;
-import kdt.web_ide.members.entity.repository.RefreshTokenRepository;
+import kdt.web_ide.members.kakao.KakaoReissueParams;
+import kdt.web_ide.members.oAuth.OAuthInfoResponse;
+import kdt.web_ide.members.oAuth.OAuthLoginParams;
+import kdt.web_ide.members.oAuth.RequestOAuthInfoService;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
+@Transactional
public class MemberService {
private final MemberRepository memberRepository;
- private final PasswordEncoder passwordEncoder;
+ private final RequestOAuthInfoService requestOAuthInfoService;
private final JwtProvider jwtProvider;
- private final RefreshTokenRepository refreshTokenRepository;
-
private final S3Uploader s3Uploader;
- @Transactional
- public void saveRefreshToken(TokenResponse tokenDto) {
- RefreshToken refreshToken =
- RefreshToken.builder()
- .keyUserId(tokenDto.getKey())
- .refreshToken(tokenDto.getRefreshToken())
- .build();
- String userId = refreshToken.getKeyUserId();
-
- if (refreshTokenRepository.existsByKeyUserId(userId)) {
- refreshTokenRepository.deleteByKeyUserId(userId);
- }
- refreshTokenRepository.save(refreshToken);
- }
+ public LoginResponseDto login(OAuthLoginParams params) {
+ OAuthInfoResponse oAuthInfoResponse = requestOAuthInfoService.request(params);
- public RefreshToken getRefreshToken(String refreshToken) {
- return refreshTokenRepository
- .findByRefreshToken(refreshToken)
- .orElseThrow(() -> new CustomException(ErrorCode.INVALID_TOKEN));
- }
+ Long memberId = findOrCreateMember(oAuthInfoResponse);
- public String validateRefreshToken(String refreshToken) {
- RefreshToken getRefreshToken = getRefreshToken(refreshToken);
- String createdAccessToken = jwtProvider.validateRefreshToken(getRefreshToken);
+ String accessToken = jwtProvider.generateAccessToken(memberId);
+ String refreshToken = jwtProvider.generateRefreshToken(memberId);
- if (createdAccessToken == null) {
- throw new CustomException(ErrorCode.TOKEN_EXPIRED);
- }
+ Member member = findMember(memberId);
+ member.setRefreshToken(refreshToken);
+ memberRepository.save(member);
- return createdAccessToken;
+ return LoginResponseDto.builder()
+ .member(member)
+ .tokenResponse(new TokenResponse(accessToken, refreshToken))
+ .build();
}
- // 회원가입
- public MemberResponse signUp(@Valid JoinRequestDto joinRequest) throws CustomException {
- String loginId = joinRequest.getLoginId();
- String nickName = joinRequest.getNickName();
- String password = passwordEncoder.encode(joinRequest.getPassword());
-
- // 닉네임 중복 확인
- if (memberRepository.findByNickName(nickName).isPresent()) {
- throw new CustomException(ErrorCode.DUPLICATE_NAME);
- }
-
- // 아이디 중복 확인
- if (memberRepository.findByLoginId(loginId).isPresent()) {
- throw new CustomException(ErrorCode.HAS_ID);
- }
-
- // 비밀번호 일치 확인
- if (password.equals(joinRequest.getPassword2())) {
- throw new CustomException(ErrorCode.PASSWORD_NOT_MATCHED);
- }
+ public Long findOrCreateMember(OAuthInfoResponse oAuthInfoResponse) {
+ return memberRepository
+ .findByKakaoId(oAuthInfoResponse.getKakaoId())
+ .map(Member::getMemberId)
+ .orElseGet(() -> newUser(oAuthInfoResponse));
+ }
- RoleType role = RoleType.USER;
- Member member = joinRequest.toEntity(role, password);
+ private Long newUser(OAuthInfoResponse oAuthInfoResponse) {
+ return memberRepository
+ .save(
+ Member.builder()
+ .kakaoId(oAuthInfoResponse.getKakaoId())
+ .nickName(oAuthInfoResponse.getKakaoNickname())
+ .identificationCode(
+ oAuthInfoResponse.getKakaoNickname()
+ + oAuthInfoResponse.getKakaoId().toString())
+ .profileImage(oAuthInfoResponse.getKakaoProfileImage())
+ .build())
+ .getMemberId();
+ }
- // 기본 프로필 이미지 설정
- final String DEFAULT_PROFILE_IMAGE_URL =
- "https://ide-project-bucket.s3.ap-northeast-2.amazonaws.com/profile-image/4510b03e-aded-43f1-b063-ccda7c734681_79516d5a-bdb1-4fbd-918e-6c56a38705c75070529700289430514_코에듀_기본_프로필.png";
- member.updateImage(DEFAULT_PROFILE_IMAGE_URL);
+ public TokenResponse reissue(KakaoReissueParams params) {
- memberRepository.save(member); // 회원 정보 저장
- return new MemberResponse(member);
- }
+ String refreshToken = params.getRefreshToken();
- // 로그인
- @Transactional
- public LoginResponseDto login(LoginRequestDto loginRequest) throws CustomException {
- String loginId = loginRequest.getLoginId();
- String password = loginRequest.getPassword();
+ Long memberId = jwtProvider.parseRefreshToken(refreshToken);
Member member =
memberRepository
- .findByLoginId(loginId)
- .orElseThrow(() -> new CustomException(ErrorCode.INVALID_LOGINID));
+ .findById(memberId)
+ .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
- if (!passwordEncoder.matches(password, member.getPassword())) {
- throw new CustomException(ErrorCode.INVALID_PASSWORD);
+ if (!refreshToken.equals(member.getRefreshToken())) {
+ throw new CustomException(ErrorCode.INVALID_TOKEN);
}
- CustomUserInfoDto userInfoDto =
- new CustomUserInfoDto(member.getMemberId(), member.getLoginId(), member.getRoles());
- TokenResponse tokenDto = jwtProvider.createTokenByLogin(userInfoDto);
- saveRefreshToken(tokenDto);
- return new LoginResponseDto(member, tokenDto);
+ String newAccessToken = jwtProvider.generateAccessToken(member.getMemberId());
+ String newRefreshToken = jwtProvider.generateRefreshToken(member.getMemberId());
+
+ member.setRefreshToken(newRefreshToken);
+
+ return new TokenResponse(newAccessToken, newRefreshToken);
+ }
+
+ public Member findMember(Long memberId) {
+ return memberRepository
+ .findById(memberId)
+ .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
}
// 멤버 정보 반환
@@ -137,7 +113,7 @@ public MemberResponse updateProfileImage(MultipartFile image, Member member) thr
throw new CustomException(ErrorCode.INVALID_IMAGE);
}
String uploadedUrl = s3Uploader.upload(image, "profile-image");
- member.updateImage(uploadedUrl);
+ member.setProfileImage(uploadedUrl);
memberRepository.save(member);
return new MemberResponse(member);
}
@@ -151,21 +127,7 @@ public MemberResponse updateNickName(String newNickName, Member member) {
if (memberRepository.findByNickName(newNickName).isPresent()) {
throw new CustomException(ErrorCode.DUPLICATE_NAME);
}
- member.updateNickName(newNickName);
- memberRepository.save(member);
- return new MemberResponse(member);
- }
-
- // 로그인 아이디 수정
- @Transactional
- public MemberResponse updateLoginId(String newLoginId, Member member) {
- if (newLoginId == null || newLoginId.trim().isEmpty()) {
- throw new CustomException(ErrorCode.INVALID_LOGINID);
- }
- if (memberRepository.findByLoginId(newLoginId).isPresent()) {
- throw new CustomException(ErrorCode.HAS_ID);
- }
- member.updateLoginId(newLoginId);
+ member.setNickName(newNickName);
memberRepository.save(member);
return new MemberResponse(member);
}
diff --git a/src/main/java/kdt/web_ide/members/service/filter/JwtAuthFilter.java b/src/main/java/kdt/web_ide/members/service/filter/JwtAuthFilter.java
index f20ae7d..6ca2668 100644
--- a/src/main/java/kdt/web_ide/members/service/filter/JwtAuthFilter.java
+++ b/src/main/java/kdt/web_ide/members/service/filter/JwtAuthFilter.java
@@ -11,10 +11,13 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
-import io.jsonwebtoken.Claims;
+import kdt.web_ide.common.exception.CustomException;
+import kdt.web_ide.common.exception.ErrorCode;
+import kdt.web_ide.members.service.CustomUserDetailService;
import kdt.web_ide.members.service.JwtProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -25,24 +28,31 @@
public class JwtAuthFilter extends GenericFilterBean {
private final JwtProvider jwtProvider;
+ private final CustomUserDetailService customUserDetailService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
+
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 헤더에서 JWT 토큰을 가져옴
String token = jwtProvider.resolveToken(httpRequest);
- if (token != null && jwtProvider.validateToken(token)) {
- // JWT 토큰에서 loginId 추철
- Claims claims = jwtProvider.getUserInfoFromToken(token);
- String loginId = claims.get("loginId", String.class);
-
- if (loginId != null) {
- Authentication authentication = jwtProvider.createUserAuthentication(loginId);
- SecurityContextHolder.getContext().setAuthentication(authentication);
+ if (token != null) {
+ if (jwtProvider.validateToken(token)) {
+ Long memberId = Long.parseLong(jwtProvider.getUserInfoFromToken(token).getSubject());
+ UserDetails userDetails = customUserDetailService.loadUserByUsername(memberId.toString());
+
+ if (userDetails != null) {
+ Authentication authentication = jwtProvider.createUserAuthentication(memberId.toString());
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ } else {
+ throw new CustomException(ErrorCode.USER_NOT_FOUND);
+ }
+ } else {
+ throw new CustomException(ErrorCode.INVALID_TOKEN);
}
}
// 필터 체인을 계속 진행
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 916dd3e..674f37b 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -18,3 +18,10 @@ cloud:
region: ${AWS_REGION}
s3:
bucket: ${AWS_S3_BUCKET}
+oauth:
+ kakao:
+ client-id: ${KAKAO_CLIENT_ID}
+ client-secret: ${KAKAO_CLIENT_SECRET}
+ url:
+ auth: https://kauth.kakao.com
+ api: https://kapi.kakao.com