From eee16556bc1fb889c213e5b0803aaf128045691f Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Tue, 27 Feb 2024 22:51:14 +0900 Subject: [PATCH 1/8] refactor: merge --- .../global/jwt/JwtAuthenticationFilter.java | 2 ++ .../global/jwt/JwtTokenProvider.java | 19 ++++++++++++++++++- .../module/file/application/FileService.java | 11 +++++++---- .../member/application/MemberService.java | 13 ++++++++----- .../module/member/dto/LoginSuccessDto.java | 3 +-- .../member/presentation/MemberController.java | 19 +++++++++++++------ 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java b/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java index 224fb46f0..0898b7203 100644 --- a/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java @@ -35,4 +35,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha } chain.doFilter(request, response); } + + } diff --git a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java index 9d07467b3..0aaa88d6a 100644 --- a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java +++ b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java @@ -84,12 +84,29 @@ public Authentication getAuthentication(String token) { // http 헤더로부터 bearer 토큰 가져옴 public String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); - if (bearerToken != null && bearerToken.startsWith("bearer ")) { + log.info("bearerToken={}", bearerToken); + if (bearerToken != null && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); // 실제 토큰만 추출 } return null; } + public String getPayload(String token) { + return tokenToJws(token).getBody().getSubject(); + } + + private Jws tokenToJws(final String token) { + try { + return Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token); + } catch (final IllegalArgumentException | MalformedJwtException e) { + throw new IllegalArgumentException("Token이 null이거나 Token 파싱 오류"); + } catch (final SignatureException e) { + throw new IllegalArgumentException("토큰의 시크릿 키가 일치하지 않습니다."); + } catch (final ExpiredJwtException e) { + throw new IllegalArgumentException("만료된 토큰 입니다."); + } + } + // 토큰 유효성, 만료일자 확인 public boolean validateToken(String token) { try { diff --git a/src/main/java/balancetalk/module/file/application/FileService.java b/src/main/java/balancetalk/module/file/application/FileService.java index b4968630b..25304bba4 100644 --- a/src/main/java/balancetalk/module/file/application/FileService.java +++ b/src/main/java/balancetalk/module/file/application/FileService.java @@ -71,14 +71,17 @@ public ResponseEntity downloadFile(Long fileId) { if (contentType == null) { contentType = "application/octet-stream"; } + + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType(contentType)) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getOriginalName() + "\"") + .body(resource); + } catch (IOException e) { throw new BalanceTalkException(FILE_DOWNLOAD_FAILED); } - return ResponseEntity.ok() - .contentType(MediaType.parseMediaType(contentType)) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getUploadName() + "\"") - .body(resource); + } private FileType convertMimeTypeToFileType(String mimeType) { diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 73eda7095..40c49dfc1 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -7,8 +7,10 @@ import balancetalk.module.member.domain.Member; import balancetalk.module.member.domain.MemberRepository; import balancetalk.module.member.dto.*; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -48,13 +50,12 @@ public LoginSuccessDto login(final LoginDto loginDto) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword()) ); - + TokenDto tokenDto = new TokenDto("Bearer", jwtTokenProvider.createAccessToken(authentication), jwtTokenProvider.createRefreshToken(authentication)); return LoginSuccessDto.builder() .email(member.getEmail()) .password(member.getPassword()) .role(member.getRole()) - .accessToken(jwtTokenProvider.createAccessToken(authentication)) - .refreshToken(jwtTokenProvider.createRefreshToken(authentication)) + .tokenDto(tokenDto) .build(); } catch (BadCredentialsException e) { throw new BadCredentialsException("credential 오류!!"); @@ -62,8 +63,10 @@ public LoginSuccessDto login(final LoginDto loginDto) { } @Transactional(readOnly = true) - public MemberResponseDto findById(Long id) { - Member member = memberRepository.findById(id) + public MemberResponseDto findById(HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); return MemberResponseDto.fromEntity(member); } diff --git a/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java b/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java index 4d032b6d9..bfe3e5096 100644 --- a/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java +++ b/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java @@ -20,7 +20,6 @@ public class LoginSuccessDto { @Schema(description = "회원 역할", example = "USER") private Role role; - private String accessToken; + private TokenDto tokenDto; - private String refreshToken; } diff --git a/src/main/java/balancetalk/module/member/presentation/MemberController.java b/src/main/java/balancetalk/module/member/presentation/MemberController.java index c36c0332f..4b3bee35d 100644 --- a/src/main/java/balancetalk/module/member/presentation/MemberController.java +++ b/src/main/java/balancetalk/module/member/presentation/MemberController.java @@ -1,5 +1,6 @@ package balancetalk.module.member.presentation; +import balancetalk.global.jwt.JwtTokenProvider; import balancetalk.module.member.application.MemberService; import balancetalk.module.member.dto.*; import io.swagger.v3.oas.annotations.Operation; @@ -7,10 +8,12 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import java.util.List; +@Slf4j @RestController @RequiredArgsConstructor @Tag(name = "member", description = "회원 API") @@ -18,7 +21,6 @@ public class MemberController { private final MemberService memberService; - @ResponseStatus(HttpStatus.CREATED) @PostMapping("/join") @Operation(summary = "회원 가입", description = "닉네임, 이메일, 비밀번호를 입력하여 회원 가입을 한다.") @@ -37,14 +39,14 @@ public LoginSuccessDto login(@Valid @RequestBody LoginDto loginDto) { } @ResponseStatus(HttpStatus.OK) - @GetMapping("/{memberId}") - @Operation(summary = "단일 회원 조회", description = "해당 id값과 일치하는 회원 정보를 조회한다.") - public MemberResponseDto findMemberInfo(@PathVariable("memberId") Long memberId) { - return memberService.findById(memberId); + @GetMapping("/find") + @Operation(summary = "단일 회원 조회", description = "해당 jwt 토큰 값과 일치하는 회원 정보를 조회한다.") + public MemberResponseDto findMemberInfo(HttpServletRequest request) { + return memberService.findById(request); } @ResponseStatus(HttpStatus.OK) - @GetMapping + @GetMapping("/findAll") @Operation(summary = "전체 회원 조회", description = "모든 회원 정보를 조회한다.") public List findAllMemberInfo() { return memberService.findAll(); @@ -73,4 +75,9 @@ public String deleteMember(@PathVariable("memberId") Long memberId, @Valid @Requ memberService.delete(memberId, loginDto); return "회원 탈퇴가 정상적으로 처리되었습니다."; } + + @PostMapping("/test") + public String test() { + return "success"; + } } From 82aef001bf703e1022df43ef4b2f789678d0aa29 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Tue, 27 Feb 2024 22:51:41 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=ED=86=A0=ED=81=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=A0=20=EB=95=8C=20grantType=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../balancetalk/module/member/dto/TokenDto.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/balancetalk/module/member/dto/TokenDto.java diff --git a/src/main/java/balancetalk/module/member/dto/TokenDto.java b/src/main/java/balancetalk/module/member/dto/TokenDto.java new file mode 100644 index 000000000..d9a2fe9ea --- /dev/null +++ b/src/main/java/balancetalk/module/member/dto/TokenDto.java @@ -0,0 +1,15 @@ +package balancetalk.module.member.dto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TokenDto { + private String grantType; + private String accessToken; + private String refreshToken; +} From cd3bea84b89c4c80c35baa6580d262565ea2c283 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Tue, 27 Feb 2024 22:54:47 +0900 Subject: [PATCH 3/8] =?UTF-8?q?Todo:=20jwt=20=ED=86=A0=ED=81=B0=EC=9D=84?= =?UTF-8?q?=20=EC=B6=94=EC=B6=9C=ED=95=98=EB=8A=94=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EC=98=88=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/balancetalk/global/jwt/JwtUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/balancetalk/global/jwt/JwtUtils.java diff --git a/src/main/java/balancetalk/global/jwt/JwtUtils.java b/src/main/java/balancetalk/global/jwt/JwtUtils.java new file mode 100644 index 000000000..11f5a58a5 --- /dev/null +++ b/src/main/java/balancetalk/global/jwt/JwtUtils.java @@ -0,0 +1,6 @@ +package balancetalk.global.jwt; + +public class JwtUtils { + + // TODO: static으로 메서드 선언 & member 조회 까지 +} From 68d473124711fb0ac938fed9778cfee00891968c Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Wed, 28 Feb 2024 00:14:39 +0900 Subject: [PATCH 4/8] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95,=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20memberId=20->=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberService.java | 31 ++++++++++--------- .../member/domain/MemberRepository.java | 1 + .../member/presentation/MemberController.java | 22 ++++++------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 40c49dfc1..9ee39b82d 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -3,14 +3,12 @@ import balancetalk.global.exception.BalanceTalkException; import balancetalk.global.exception.ErrorCode; import balancetalk.global.jwt.JwtTokenProvider; -import balancetalk.global.redis.application.RedisService; import balancetalk.module.member.domain.Member; import balancetalk.module.member.domain.MemberRepository; import balancetalk.module.member.dto.*; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -80,31 +78,36 @@ public List findAll() { } @Transactional - public void updateNickname(Long memberId, final NicknameUpdate nicknameUpdate) { - Member member = memberRepository.findById(memberId) + public void updateNickname(final NicknameUpdate nicknameUpdate, HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); member.updateNickname(nicknameUpdate.getNickname()); } @Transactional - public void updatePassword(Long memberId, final PasswordUpdate passwordUpdate) { - Member member = memberRepository.findById(memberId) + public void updatePassword(final PasswordUpdate passwordUpdate, HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); - member.updatePassword(passwordUpdate.getPassword()); + member.updatePassword(passwordEncoder.encode(passwordUpdate.getPassword())); } @Transactional - public void delete(Long memberId, final LoginDto loginDto) { - Member member = memberRepository.findById(memberId) + public void delete(final LoginDto loginDto, HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); - if (!member.getEmail().equals(loginDto.getEmail())) { throw new BalanceTalkException(ErrorCode.FORBIDDEN_MEMBER_DELETE); } - if (!member.getPassword().equals(loginDto.getPassword())) { - throw new BalanceTalkException(ErrorCode.INCORRECT_PASSWORD); - } - memberRepository.deleteById(memberId); + if (!passwordEncoder.matches(loginDto.getPassword(), member.getPassword())) { + throw new BalanceTalkException(ErrorCode.MISMATCHED_EMAIL_OR_PASSWORD); + } + memberRepository.deleteByEmail(email); } } diff --git a/src/main/java/balancetalk/module/member/domain/MemberRepository.java b/src/main/java/balancetalk/module/member/domain/MemberRepository.java index a1d8cd1d8..8ac4abb8b 100644 --- a/src/main/java/balancetalk/module/member/domain/MemberRepository.java +++ b/src/main/java/balancetalk/module/member/domain/MemberRepository.java @@ -4,4 +4,5 @@ import java.util.Optional; public interface MemberRepository extends JpaRepository { Optional findByEmail(String username); + void deleteByEmail(String email); } diff --git a/src/main/java/balancetalk/module/member/presentation/MemberController.java b/src/main/java/balancetalk/module/member/presentation/MemberController.java index 4b3bee35d..c88bd67f1 100644 --- a/src/main/java/balancetalk/module/member/presentation/MemberController.java +++ b/src/main/java/balancetalk/module/member/presentation/MemberController.java @@ -53,31 +53,27 @@ public List findAllMemberInfo() { } @ResponseStatus(HttpStatus.OK) - @PutMapping("/nickname/{memberId}") + @PutMapping("/update/nickname") @Operation(summary = "회원 닉네임 수정", description = "회원 닉네임을 수정한다.") - public String updateNickname(@PathVariable("memberId") Long memberId, @Valid @RequestBody NicknameUpdate nicknameUpdate) { - memberService.updateNickname(memberId, nicknameUpdate); + public String updateNickname(@Valid @RequestBody NicknameUpdate nicknameUpdate, HttpServletRequest request) { + memberService.updateNickname(nicknameUpdate, request); return "회원 닉네임이 변경되었습니다."; } @ResponseStatus(HttpStatus.OK) - @PutMapping("/{memberId}") + @PutMapping("/update/password") @Operation(summary = "회원 비밀번호 수정", description = "회원 패스워드를 수정한다.") - public String updatePassword(@PathVariable("memberId") Long memberId, @Valid @RequestBody PasswordUpdate passwordUpdate) { - memberService.updatePassword(memberId, passwordUpdate); + public String updatePassword(@Valid @RequestBody PasswordUpdate passwordUpdate, HttpServletRequest request) { + memberService.updatePassword(passwordUpdate, request); return "회원 비밀번호가 변경되었습니다."; } @ResponseStatus(HttpStatus.OK) - @DeleteMapping("/{memberId}") + @DeleteMapping("/delete") @Operation(summary = "회원 삭제", description = "해당 id값과 일치하는 회원 정보를 삭제한다.") - public String deleteMember(@PathVariable("memberId") Long memberId, @Valid @RequestBody LoginDto loginDto) { - memberService.delete(memberId, loginDto); + public String deleteMember(@Valid @RequestBody LoginDto loginDto, HttpServletRequest request) { + memberService.delete(loginDto, request); return "회원 탈퇴가 정상적으로 처리되었습니다."; } - @PostMapping("/test") - public String test() { - return "success"; - } } From 6fad4caca3ef6eedf4483314cd0cce87d11dff48 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Wed, 28 Feb 2024 00:16:15 +0900 Subject: [PATCH 5/8] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20memberId?= =?UTF-8?q?=20=EA=B0=92=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/balancetalk/module/member/dto/MemberResponseDto.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java b/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java index 6a55a220e..41ac96819 100644 --- a/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java +++ b/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java @@ -13,6 +13,9 @@ @AllArgsConstructor public class MemberResponseDto { + @Schema(description = "회원 id", example = "1") + private Long id; + @Schema(description = "회원 닉네임", example = "닉네임") private String nickname; @Schema(description = "회원 프로필", example = "../") @@ -28,6 +31,7 @@ public class MemberResponseDto { public static MemberResponseDto fromEntity(Member member) { return MemberResponseDto.builder() + .id(member.getId()) .nickname(member.getNickname()) //.profilePhoto(file.getPath()) .createdAt(member.getCreatedAt()) From be851052e40df65a44a5aa9da0b29f8bd1b757f5 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Wed, 28 Feb 2024 01:37:42 +0900 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=EC=9D=84=20jwt=20=ED=86=A0=ED=81=B0=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=B6=94=EC=B6=9C=ED=95=98=EB=8A=94=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/JwtTokenProvider.java | 3 +- .../member/application/MemberService.java | 32 ++++++++----------- .../member/presentation/MemberController.java | 2 +- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java index 0aaa88d6a..0c6482f9a 100644 --- a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java +++ b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java @@ -84,7 +84,6 @@ public Authentication getAuthentication(String token) { // http 헤더로부터 bearer 토큰 가져옴 public String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); - log.info("bearerToken={}", bearerToken); if (bearerToken != null && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); // 실제 토큰만 추출 } @@ -95,7 +94,7 @@ public String getPayload(String token) { return tokenToJws(token).getBody().getSubject(); } - private Jws tokenToJws(final String token) { + public Jws tokenToJws(final String token) { try { return Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token); } catch (final IllegalArgumentException | MalformedJwtException e) { diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 9ee39b82d..163d065f3 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -61,11 +61,8 @@ public LoginSuccessDto login(final LoginDto loginDto) { } @Transactional(readOnly = true) - public MemberResponseDto findById(HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + public MemberResponseDto findMember(HttpServletRequest request) { + Member member = extractMember(request); return MemberResponseDto.fromEntity(member); } @@ -79,28 +76,19 @@ public List findAll() { @Transactional public void updateNickname(final NicknameUpdate nicknameUpdate, HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + Member member = extractMember(request); member.updateNickname(nicknameUpdate.getNickname()); } @Transactional public void updatePassword(final PasswordUpdate passwordUpdate, HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + Member member = extractMember(request); member.updatePassword(passwordEncoder.encode(passwordUpdate.getPassword())); } @Transactional public void delete(final LoginDto loginDto, HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + Member member = extractMember(request); if (!member.getEmail().equals(loginDto.getEmail())) { throw new BalanceTalkException(ErrorCode.FORBIDDEN_MEMBER_DELETE); } @@ -108,6 +96,14 @@ public void delete(final LoginDto loginDto, HttpServletRequest request) { if (!passwordEncoder.matches(loginDto.getPassword(), member.getPassword())) { throw new BalanceTalkException(ErrorCode.MISMATCHED_EMAIL_OR_PASSWORD); } - memberRepository.deleteByEmail(email); + memberRepository.deleteByEmail(member.getEmail()); + } + + private Member extractMember(HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) + .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + return member; } } diff --git a/src/main/java/balancetalk/module/member/presentation/MemberController.java b/src/main/java/balancetalk/module/member/presentation/MemberController.java index c88bd67f1..9c56ad602 100644 --- a/src/main/java/balancetalk/module/member/presentation/MemberController.java +++ b/src/main/java/balancetalk/module/member/presentation/MemberController.java @@ -42,7 +42,7 @@ public LoginSuccessDto login(@Valid @RequestBody LoginDto loginDto) { @GetMapping("/find") @Operation(summary = "단일 회원 조회", description = "해당 jwt 토큰 값과 일치하는 회원 정보를 조회한다.") public MemberResponseDto findMemberInfo(HttpServletRequest request) { - return memberService.findById(request); + return memberService.findMember(request); } @ResponseStatus(HttpStatus.OK) From 252a7580b728a24afd362b496111714a55c23310 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Wed, 28 Feb 2024 22:25:08 +0900 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20pr=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=ED=95=B4=EC=84=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/JwtAuthenticationFilter.java | 8 ++------ .../balancetalk/global/jwt/JwtTokenProvider.java | 2 -- .../module/member/application/MemberService.java | 5 +++-- .../member/presentation/MemberController.java | 14 +++++++------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java b/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java index 0898b7203..b4c746875 100644 --- a/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/balancetalk/global/jwt/JwtAuthenticationFilter.java @@ -1,5 +1,6 @@ package balancetalk.global.jwt; +import io.jsonwebtoken.ExpiredJwtException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; @@ -10,9 +11,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.GenericFilterBean; - import java.io.IOException; - @RequiredArgsConstructor public class JwtAuthenticationFilter extends GenericFilterBean { @@ -21,7 +20,6 @@ public class JwtAuthenticationFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String token = jwtTokenProvider.resolveToken((HttpServletRequest) request); - try { if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); @@ -30,11 +28,9 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha } catch (RedisConnectionFailureException e) { SecurityContextHolder.clearContext(); throw new IllegalAccessError("Redis 연결 실패"); - } catch (Exception e) { + } catch (ExpiredJwtException e) { throw new IllegalArgumentException("JWT가 유효하지 않음."); } chain.doFilter(request, response); } - - } diff --git a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java index 0c6482f9a..6f564288e 100644 --- a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java +++ b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java @@ -76,9 +76,7 @@ public String createRefreshToken(Authentication authentication) { public Authentication getAuthentication(String token) { String userPrincipal = Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token).getBody().getSubject(); UserDetails userDetails = userDetailsService.loadUserByUsername(userPrincipal); - return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); - } // http 헤더로부터 bearer 토큰 가져옴 diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 163d065f3..dbbb376e4 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -61,8 +61,9 @@ public LoginSuccessDto login(final LoginDto loginDto) { } @Transactional(readOnly = true) - public MemberResponseDto findMember(HttpServletRequest request) { - Member member = extractMember(request); + public MemberResponseDto findById(Long id) { + Member member = memberRepository.findById(id) + .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); return MemberResponseDto.fromEntity(member); } diff --git a/src/main/java/balancetalk/module/member/presentation/MemberController.java b/src/main/java/balancetalk/module/member/presentation/MemberController.java index 9c56ad602..24021ec05 100644 --- a/src/main/java/balancetalk/module/member/presentation/MemberController.java +++ b/src/main/java/balancetalk/module/member/presentation/MemberController.java @@ -39,21 +39,21 @@ public LoginSuccessDto login(@Valid @RequestBody LoginDto loginDto) { } @ResponseStatus(HttpStatus.OK) - @GetMapping("/find") - @Operation(summary = "단일 회원 조회", description = "해당 jwt 토큰 값과 일치하는 회원 정보를 조회한다.") - public MemberResponseDto findMemberInfo(HttpServletRequest request) { - return memberService.findMember(request); + @GetMapping("/{memberId}") + @Operation(summary = "단일 회원 조회", description = "memberId와 일치하는 회원 정보를 조회한다.") + public MemberResponseDto findMemberInfo(@PathVariable("memberId") Long memberId) { + return memberService.findById(memberId); } @ResponseStatus(HttpStatus.OK) - @GetMapping("/findAll") + @GetMapping @Operation(summary = "전체 회원 조회", description = "모든 회원 정보를 조회한다.") public List findAllMemberInfo() { return memberService.findAll(); } @ResponseStatus(HttpStatus.OK) - @PutMapping("/update/nickname") + @PutMapping("/nickname") @Operation(summary = "회원 닉네임 수정", description = "회원 닉네임을 수정한다.") public String updateNickname(@Valid @RequestBody NicknameUpdate nicknameUpdate, HttpServletRequest request) { memberService.updateNickname(nicknameUpdate, request); @@ -61,7 +61,7 @@ public String updateNickname(@Valid @RequestBody NicknameUpdate nicknameUpdate, } @ResponseStatus(HttpStatus.OK) - @PutMapping("/update/password") + @PutMapping("/password") @Operation(summary = "회원 비밀번호 수정", description = "회원 패스워드를 수정한다.") public String updatePassword(@Valid @RequestBody PasswordUpdate passwordUpdate, HttpServletRequest request) { memberService.updatePassword(passwordUpdate, request); From 338f600473c01ae32ae451d6ce4509e6d4751267 Mon Sep 17 00:00:00 2001 From: Junsoo Choi Date: Thu, 29 Feb 2024 00:14:42 +0900 Subject: [PATCH 8/8] =?UTF-8?q?refactor:=20merge=EA=B3=BC=EC=A0=95?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=82=AD=EC=A0=9C=EB=90=9C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/JwtTokenProvider.java | 29 +++++++++---------- .../member/application/MemberService.java | 9 +++--- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java index 83e4f1b99..74aa466c6 100644 --- a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java +++ b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java @@ -1,6 +1,9 @@ package balancetalk.global.jwt; +import balancetalk.global.exception.BalanceTalkException; +import balancetalk.global.exception.ErrorCode; import balancetalk.global.redis.application.RedisService; +import balancetalk.module.member.dto.TokenDto; import io.jsonwebtoken.*; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -104,22 +107,6 @@ private Jws tokenToJws(final String token) { } } - public String getPayload(String token) { - return tokenToJws(token).getBody().getSubject(); - } - - public Jws tokenToJws(final String token) { - try { - return Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token); - } catch (final IllegalArgumentException | MalformedJwtException e) { - throw new IllegalArgumentException("Token이 null이거나 Token 파싱 오류"); - } catch (final SignatureException e) { - throw new IllegalArgumentException("토큰의 시크릿 키가 일치하지 않습니다."); - } catch (final ExpiredJwtException e) { - throw new IllegalArgumentException("만료된 토큰 입니다."); - } - } - // 토큰 유효성, 만료일자 확인 public boolean validateToken(String token) { try { @@ -138,6 +125,16 @@ private void validateAuthentication(Authentication authentication) { if (authentication == null) { throw new IllegalArgumentException("유저 정보가 존재하지 않습니다."); } + } + + public TokenDto reissueToken(String refreshToken) { + validateToken(refreshToken); + Authentication authentication = getAuthentication(refreshToken); + // redis에 저장된 RefreshToken 값을 가져옴 + String redisRefreshToken = redisService.getValues(authentication.getName()); + if (!redisRefreshToken.equals(refreshToken)) { + throw new BalanceTalkException(ErrorCode.INVALID_REFRESH_TOKEN); + } TokenDto tokenDto = new TokenDto( "Bearer", createAccessToken(authentication), diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 957d5d4fa..3a1edac19 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -49,7 +49,8 @@ public LoginSuccessDto login(final LoginDto loginDto) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword()) ); - TokenDto tokenDto = new TokenDto("Bearer", jwtTokenProvider.createAccessToken(authentication), jwtTokenProvider.createRefreshToken(authentication)); + String refreshToken = jwtTokenProvider.createRefreshToken(authentication); + TokenDto tokenDto = jwtTokenProvider.reissueToken(refreshToken); // 만료되었다면, 재발급 return LoginSuccessDto.builder() .email(member.getEmail()) .password(member.getPassword()) @@ -62,10 +63,8 @@ public LoginSuccessDto login(final LoginDto loginDto) { } @Transactional(readOnly = true) - public MemberResponseDto findById(HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) + public MemberResponseDto findById(Long id) { + Member member = memberRepository.findById(id) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); return MemberResponseDto.fromEntity(member); }