Skip to content

Commit 592bfa6

Browse files
authored
Merge pull request #159 from SWU-Elixir/feat/136-social-login
feat: 소셜 회원용 회원가입 성공 시 토큰 발급 기능 추가
2 parents 4911dd7 + 546c5ed commit 592bfa6

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

src/main/java/BE_Elixir/Elixir/domain/member/controller/MemberController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package BE_Elixir.Elixir.domain.member.controller;
22

3+
import BE_Elixir.Elixir.domain.auth.dto.response.TokenResponseDTO;
34
import BE_Elixir.Elixir.domain.follow.service.FollowService;
45
import BE_Elixir.Elixir.domain.member.controller.api.MemberApi;
6+
import BE_Elixir.Elixir.domain.member.dto.SocialSignUpDTO;
57
import BE_Elixir.Elixir.domain.member.dto.request.*;
68
import BE_Elixir.Elixir.domain.member.dto.response.*;
79
import BE_Elixir.Elixir.domain.member.entity.Member;
@@ -64,18 +66,18 @@ public ResponseEntity<CommonResponse<?>> signUp(
6466

6567
// 소셜 회원용 회원가입
6668
@PostMapping(value= "/signup/{loginType}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
67-
public ResponseEntity<CommonResponse<?>> socialSignUp(
69+
public ResponseEntity<CommonResponse<TokenResponseDTO>> socialSignUp(
6870
@PathVariable(name="loginType") LoginType loginType,
6971
@RequestPart("dto") SocialSignUpRequestDTO dto,
7072
@RequestPart(value = "profileImage", required = false) MultipartFile profileImage
7173
) {
7274
log.info("소셜 회원용 회원가입 요청 - 이메일: {}", dto.getEmail());
7375

74-
Member member = memberService.socialSignUp(loginType, dto, profileImage);
75-
log.info("소셜 회원용 회원가입 성공 - 회원 ID: {}", member.getId());
76+
SocialSignUpDTO socialSignUpDTO = memberService.socialSignUp(loginType, dto, profileImage);
77+
log.info("소셜 회원용 회원가입 성공 - 회원 ID: {}", socialSignUpDTO.getMember().getId());
7678
return ResponseEntity.status(HttpStatus.CREATED)
7779
.body(CommonResponse.success(HttpStatus.CREATED.value(), HttpStatus.CREATED.toString(),
78-
"소셜 회원용 회원가입 성공 - memberId: " + member.getId()));
80+
"소셜 회원용 회원가입 성공 - memberId: " + socialSignUpDTO.getMember().getId(), socialSignUpDTO.getTokenResponseDTO()));
7981
}
8082

8183
// 이메일 인증 요청하기

src/main/java/BE_Elixir/Elixir/domain/member/controller/api/MemberApi.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package BE_Elixir.Elixir.domain.member.controller.api;
22

3+
import BE_Elixir.Elixir.domain.auth.dto.response.TokenResponseDTO;
34
import BE_Elixir.Elixir.domain.member.dto.request.*;
45
import BE_Elixir.Elixir.domain.member.dto.response.*;
56
import BE_Elixir.Elixir.domain.member.entity.MemberDetails;
@@ -92,7 +93,10 @@ ResponseEntity<CommonResponse<?>> signUp(
9293
"status": 200,
9394
"code": "200 OK",
9495
"message": "소셜 회원용 회원가입 성공 - memberId: 1",
95-
"data": null
96+
"data": {
97+
"grantType": "Bearer",
98+
"accessToken": "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJtb29sMDIwODAzQGdtYWlsLmNvbSIsImF1dGgiOiJVU0VSIiwiZXhwIjoxNzUzNTk4NDQxfQ.YW8gIVXLWMFEm_ywGtDI4TTSJTHOpNVOxKG2wLeBBC2fCW_ZaG1rF7e_9Xps9gnp",
99+
"refreshToken": "eyJhbGciOiJIUzM4NCJ9.eyJleHAiOjE3NTQ4MDQ0NDF9.Ew5909EU638VuUe3gzNDUv50r162BMrZuDlJD43brRr8dSIclat71BOtPRzZZX9Q"
96100
}
97101
"""))),
98102
@ApiResponse(responseCode = "401", description = "소셜 회원용 회원가입 실패",
@@ -106,7 +110,7 @@ ResponseEntity<CommonResponse<?>> signUp(
106110
}
107111
""")))
108112
})
109-
ResponseEntity<CommonResponse<?>> socialSignUp(
113+
ResponseEntity<CommonResponse<TokenResponseDTO>> socialSignUp(
110114
@PathVariable(name="loginType") LoginType loginType,
111115
@RequestPart("dto") SocialSignUpRequestDTO dto,
112116
@RequestPart(value = "profileImage", required = false) MultipartFile profileImage
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package BE_Elixir.Elixir.domain.member.dto;
2+
3+
import BE_Elixir.Elixir.domain.auth.dto.response.TokenResponseDTO;
4+
import BE_Elixir.Elixir.domain.member.entity.Member;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
9+
@Builder
10+
@Data
11+
@AllArgsConstructor
12+
public class SocialSignUpDTO {
13+
private Member member;
14+
private TokenResponseDTO tokenResponseDTO;
15+
}

src/main/java/BE_Elixir/Elixir/domain/member/service/MemberService.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package BE_Elixir.Elixir.domain.member.service;
22

3+
import BE_Elixir.Elixir.domain.auth.dto.response.TokenResponseDTO;
4+
import BE_Elixir.Elixir.domain.member.dto.SocialSignUpDTO;
35
import BE_Elixir.Elixir.domain.member.dto.request.SignUpRequestDTO;
46
import BE_Elixir.Elixir.domain.member.dto.request.SocialSignUpRequestDTO;
57
import BE_Elixir.Elixir.domain.member.entity.Member;
8+
import BE_Elixir.Elixir.domain.member.entity.MemberDetails;
69
import BE_Elixir.Elixir.domain.member.repository.MemberRepository;
710
import BE_Elixir.Elixir.global.enums.LoginType;
811
import BE_Elixir.Elixir.global.exception.CustomException;
@@ -17,6 +20,8 @@
1720
import lombok.RequiredArgsConstructor;
1821
import lombok.extern.slf4j.Slf4j;
1922
import org.springframework.dao.DataIntegrityViolationException;
23+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
24+
import org.springframework.security.core.Authentication;
2025
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
2126
import org.springframework.stereotype.Service;
2227
import org.springframework.web.multipart.MultipartFile;
@@ -32,13 +37,13 @@
3237
public class MemberService {
3338

3439
private final MemberRepository memberRepository;
40+
private final MemberDetailsService memberDetailsService;
3541
private final BCryptPasswordEncoder passwordEncoder;
3642
private final JwtProvider jwtProvider;
3743
private final RedisAuthService redisAuthService;
3844
private final RedisEmailVerificationService redisMailVerificationService;
3945
private final S3Service s3Service;
4046
private final EmailService mailService;
41-
4247
// 이메일 중복 체크
4348
public boolean isEmailDuplicated(String email) {
4449
return memberRepository.existsByEmail(email);
@@ -104,7 +109,7 @@ public Member localSignUp(SignUpRequestDTO request, MultipartFile profileImage)
104109
}
105110

106111
// 소셜 회원용 회원가입 메소드
107-
public Member socialSignUp(LoginType loginType, SocialSignUpRequestDTO request, MultipartFile profileImage) {
112+
public SocialSignUpDTO socialSignUp(LoginType loginType, SocialSignUpRequestDTO request, MultipartFile profileImage) {
108113
// 소셜 회원이 맞는지 검증
109114
if (!loginType.isSocial()) {
110115
throw new CustomException(ErrorCode.LOGIN_TYPE_MISMATCH);
@@ -156,7 +161,27 @@ public Member socialSignUp(LoginType loginType, SocialSignUpRequestDTO request,
156161
member.setProfileUrl(request.getProfileImageUrl());
157162
}
158163

159-
return memberRepository.save(member);
164+
memberRepository.save(member);
165+
166+
// JWT 토큰 발급
167+
// Spring Security Authentication 객체 생성
168+
MemberDetails memberDetails = memberDetailsService.loadUserByUsername(member.getEmail());
169+
Authentication authentication = new UsernamePasswordAuthenticationToken(
170+
memberDetails, "", memberDetails.getAuthorities()
171+
);
172+
173+
// JWT 생성
174+
TokenResponseDTO tokenResponse = jwtProvider.generateToken(authentication);
175+
String refreshToken = tokenResponse.getRefreshToken();
176+
177+
// Redis에 Refresh Token 저장
178+
redisAuthService.saveRefreshToken(member.getEmail(), refreshToken);
179+
log.info("[소셜 로그인] Refresh Token Redis에 저장: email={}, token={}", member.getEmail(), refreshToken);
180+
181+
return SocialSignUpDTO.builder()
182+
.member(member)
183+
.tokenResponseDTO(tokenResponse)
184+
.build();
160185

161186
} catch (DataIntegrityViolationException e) {
162187
if (e.getMessage().toUpperCase().contains("EMAIL_UNIQUE")) {

0 commit comments

Comments
 (0)