forked from Fastcampus-Final-Team3/jober-backend
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 회원가입, 로그인, 로그아웃, 토큰 재발급 기능 구현(Fastcampus-Final-Team3#166)
- Loading branch information
Showing
12 changed files
with
412 additions
and
1 deletion.
There are no files selected for viewing
75 changes: 75 additions & 0 deletions
75
src/main/java/com/javajober/member/controller/MemberController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.javajober.member.controller; | ||
|
||
import javax.validation.Valid; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.validation.BindingResult; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
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.javajober.core.util.ApiResponse; | ||
import com.javajober.exception.ApiStatus; | ||
import com.javajober.exception.ApplicationException; | ||
import com.javajober.member.dto.MemberLoginRequest; | ||
import com.javajober.member.dto.MemberLoginResponse; | ||
import com.javajober.member.dto.MemberSignupRequest; | ||
import com.javajober.member.dto.MemberSignupResponse; | ||
import com.javajober.member.service.MemberService; | ||
import com.javajober.refreshToken.service.RefreshTokenService; | ||
import com.javajober.refreshToken.dto.RefreshTokenRequest; | ||
|
||
@RestController | ||
@Validated | ||
@RequestMapping("/members") | ||
public class MemberController { | ||
private final MemberService memberService; | ||
private final RefreshTokenService refreshTokenService; | ||
|
||
public MemberController(MemberService memberService, | ||
RefreshTokenService refreshTokenService) { | ||
this.memberService = memberService; | ||
this.refreshTokenService = refreshTokenService; | ||
} | ||
|
||
@PostMapping("/signup") | ||
public ResponseEntity<ApiResponse.Response<MemberSignupResponse>> signup(@RequestBody @Valid MemberSignupRequest memberSignupRequest, | ||
BindingResult bindingResult) { | ||
|
||
MemberSignupResponse data = memberService.signup(memberSignupRequest, bindingResult); | ||
|
||
return ApiResponse.response(ApiStatus.OK, "회원가입에 성공했습니다.", data); | ||
} | ||
|
||
@PostMapping("/login") | ||
public ResponseEntity<ApiResponse.Response<MemberLoginResponse>> login(@RequestBody @Valid MemberLoginRequest loginDto, BindingResult bindingResult) { | ||
try { | ||
|
||
MemberLoginResponse data = memberService.login(loginDto,bindingResult); | ||
|
||
return ApiResponse.response(ApiStatus.OK, "로그인에 성공했습니다.", data); | ||
} catch (IllegalArgumentException e) { | ||
|
||
throw new ApplicationException(ApiStatus.NO_PERMISSION, "로그인에 실패했습니다."); | ||
} | ||
} | ||
|
||
@DeleteMapping("/logout") | ||
public ResponseEntity logout(@RequestBody RefreshTokenRequest refreshTokenRequest) { | ||
|
||
refreshTokenService.deleteRefreshToken(refreshTokenRequest.getRefreshToken()); | ||
|
||
return ApiResponse.response(ApiStatus.OK, "로그인아웃에 성공했습니다.", null); | ||
} | ||
|
||
@PostMapping("/refreshToken") | ||
public ResponseEntity<ApiResponse.Response<MemberLoginResponse>> requestRefresh(@RequestBody RefreshTokenRequest refreshTokenRequest) { | ||
|
||
MemberLoginResponse data = refreshTokenService.findRefreshToken(refreshTokenRequest); | ||
|
||
return ApiResponse.response(ApiStatus.OK, "토큰 재발급에 성공했습니다.", data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/main/java/com/javajober/member/dto/MemberLoginRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.javajober.member.dto; | ||
|
||
import javax.validation.constraints.NotEmpty; | ||
import javax.validation.constraints.Pattern; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class MemberLoginRequest { | ||
public MemberLoginRequest() { | ||
|
||
} | ||
|
||
@NotEmpty | ||
@Pattern(regexp = "^[a-zA-Z0-9+-\\_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$") | ||
private String email; | ||
|
||
@NotEmpty | ||
@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*\\W).{8,20}$") // 영문, 특수문자 8자 이상 20자 이하 | ||
private String password; | ||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/javajober/member/dto/MemberLoginResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.javajober.member.dto; | ||
|
||
import com.javajober.member.domain.Member; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class MemberLoginResponse { | ||
private String accessToken; | ||
private String refreshToken; | ||
private Long memberId; | ||
private String nickname; | ||
|
||
private MemberLoginResponse(){ | ||
|
||
} | ||
|
||
@Builder | ||
public MemberLoginResponse(final String accessToken, final String refreshToken, final Long memberId, final String nickname){ | ||
this.accessToken = accessToken; | ||
this.refreshToken = refreshToken; | ||
this.memberId = memberId; | ||
this.nickname = nickname; | ||
} | ||
|
||
public MemberLoginResponse(final Member member, final String accessToken, final String refreshToken){ | ||
this.accessToken = accessToken; | ||
this.refreshToken = refreshToken; | ||
this.memberId = member.getId(); | ||
this.nickname = member.getMemberName(); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/com/javajober/member/dto/MemberSignupRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.javajober.member.dto; | ||
|
||
import javax.validation.constraints.NotEmpty; | ||
import javax.validation.constraints.Pattern; | ||
|
||
import com.javajober.member.domain.Member; | ||
import com.javajober.member.domain.MemberShipType; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class MemberSignupRequest { | ||
|
||
@NotEmpty | ||
@Pattern(regexp = "^[a-zA-Z0-9+-\\_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$", | ||
message = "이메일 형식을 맞춰야합니다") | ||
private String email; | ||
|
||
@NotEmpty | ||
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[~!@#$%^&*()+|=])[A-Za-z\\d~!@#$%^&*()+|=]{7,16}$", | ||
message = "비밀번호는 영문+숫자+특수문자를 포함한 8~20자여야 합니다") | ||
private String password; | ||
|
||
@NotEmpty | ||
@Pattern(regexp = "^[a-zA-Z가-힣\\\\s]{2,15}", | ||
message = "이름은 영문자, 한글, 공백포함 2글자부터 15글자까지 가능합니다.") | ||
private String name; | ||
|
||
private String phoneNumber; | ||
|
||
private MemberShipType memberShip; | ||
|
||
private MemberSignupRequest(){ | ||
|
||
} | ||
|
||
public static Member toEntity(final MemberSignupRequest memberSignupRequest){ | ||
return Member.builder() | ||
.memberEmail(memberSignupRequest.getEmail()) | ||
.memberName(memberSignupRequest.getName()) | ||
.phoneNumber(memberSignupRequest.getPhoneNumber()) | ||
.memberShip(memberSignupRequest.getMemberShip()) | ||
.build(); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/main/java/com/javajober/member/dto/MemberSignupResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.javajober.member.dto; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
import com.javajober.member.domain.Member; | ||
import com.javajober.member.domain.MemberShipType; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class MemberSignupResponse { | ||
private Long memberId; | ||
private String email; | ||
private String name; | ||
private String phoneNumber; | ||
private MemberShipType memberShip; | ||
private LocalDateTime regDate; | ||
|
||
private MemberSignupResponse(){ | ||
|
||
} | ||
@Builder | ||
public MemberSignupResponse(final Long memberId, final String email, final String name, final String phoneNumber, final MemberShipType memberShip, final LocalDateTime regDate){ | ||
this.memberId = memberId; | ||
this.email = email; | ||
this.name = name; | ||
this.phoneNumber = phoneNumber; | ||
this.memberShip = memberShip; | ||
this.regDate = regDate; | ||
} | ||
|
||
public MemberSignupResponse(Member member) { | ||
this.memberId = member.getId(); | ||
this.email = member.getMemberEmail(); | ||
this.name = member.getMemberName(); | ||
this.phoneNumber = member.getPhoneNumber(); | ||
this.memberShip = member.getMemberShip(); | ||
this.regDate = member.getCreatedAt(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
src/main/java/com/javajober/member/service/MemberService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.javajober.member.service; | ||
|
||
|
||
import javax.transaction.Transactional; | ||
|
||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.validation.BindingResult; | ||
|
||
import com.javajober.exception.ApiStatus; | ||
import com.javajober.exception.ApplicationException; | ||
import com.javajober.member.domain.Member; | ||
import com.javajober.member.dto.MemberLoginRequest; | ||
import com.javajober.member.dto.MemberLoginResponse; | ||
import com.javajober.member.dto.MemberSignupRequest; | ||
import com.javajober.member.dto.MemberSignupResponse; | ||
import com.javajober.member.repository.MemberRepository; | ||
import com.javajober.refreshToken.repository.RefreshTokenRepository; | ||
import com.javajober.security.JwtTokenizer; | ||
import com.javajober.refreshToken.domain.RefreshToken; | ||
|
||
@Service | ||
public class MemberService { | ||
private final MemberRepository memberRepository; | ||
private final PasswordEncoder passwordEncoder; | ||
private final JwtTokenizer jwtTokenizer; | ||
private final RefreshTokenRepository refreshTokenRepository; | ||
|
||
public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder, JwtTokenizer jwtTokenizer, | ||
RefreshTokenRepository refreshTokenRepository) { | ||
this.memberRepository = memberRepository; | ||
this.passwordEncoder = passwordEncoder; | ||
this.jwtTokenizer = jwtTokenizer; | ||
this.refreshTokenRepository = refreshTokenRepository; | ||
} | ||
|
||
@Transactional | ||
public MemberSignupResponse signup(MemberSignupRequest memberSignupRequest, BindingResult bindingResult) { | ||
if (bindingResult.hasErrors()) { | ||
throw new ApplicationException(ApiStatus.INVALID_DATA, "잘못된 요청입니다."); | ||
} | ||
|
||
Member member = memberSignupRequest.toEntity(memberSignupRequest); | ||
member.setPassword(passwordEncoder.encode(memberSignupRequest.getPassword())); | ||
Member saveMember = memberRepository.save(member); | ||
|
||
return new MemberSignupResponse(saveMember); | ||
} | ||
|
||
@Transactional | ||
public MemberLoginResponse login(MemberLoginRequest loginDto, BindingResult bindingResult) { | ||
if (bindingResult.hasErrors()) { | ||
throw new ApplicationException(ApiStatus.INVALID_DATA, "잘못된 요청입니다."); | ||
} | ||
Member member = memberRepository.findMember(loginDto.getEmail()); | ||
|
||
if (!passwordEncoder.matches(loginDto.getPassword(), member.getPassword())) { | ||
throw new ApplicationException(ApiStatus.NOT_FOUND, "비밀번호가 일치하지 않습니다."); | ||
} | ||
|
||
String accessToken = jwtTokenizer.createAccessToken(member.getId(), member.getMemberEmail()); | ||
String refreshToken = jwtTokenizer.createRefreshToken(member.getId(), member.getMemberEmail()); | ||
|
||
RefreshToken refreshTokenEntity = new RefreshToken(member.getId(),refreshToken); | ||
refreshTokenRepository.save(refreshTokenEntity); | ||
|
||
return new MemberLoginResponse(member,accessToken,refreshToken); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/com/javajober/refreshToken/domain/RefreshToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.javajober.refreshToken.domain; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.persistence.Table; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@Table(name="refresh_token") | ||
@Entity | ||
public class RefreshToken { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private Long memberId; | ||
|
||
private String value; | ||
|
||
public RefreshToken(){ | ||
|
||
} | ||
|
||
@Builder | ||
public RefreshToken(final Long memberId, final String value){ | ||
this.memberId = memberId; | ||
this.value = value; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/com/javajober/refreshToken/dto/RefreshTokenRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.javajober.refreshToken.dto; | ||
|
||
import javax.validation.constraints.NotEmpty; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class RefreshTokenRequest { | ||
|
||
@NotEmpty | ||
String refreshToken; | ||
} |
Oops, something went wrong.