사용자 기능 및 인증토큰 발행
사용자 기능
Q1) 사용자 등록시 입력값이 유효하지 않은 경우 예외를 발생시키는 기능을 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
입력값 : 이메일(ID), 이름, 비밀번호, 연락처
사용자 정의 에러 모델을 이용하여 에러를 리턴
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MemberInput {
@Email(message = "이메일 형식에 맞게 입력해 주세요.")
@NotBlank(message = "이메일은 필수 항목 입니다.")
private String email;
@NotBlank(message = "이름을 필수 항목 입니다.")
private String memberName;
@Size(min = 4, message = "비밀번호는 4자 이상 입력해야 합니다")
@NotBlank(message = "비밀번호는 필수 항목 입니다.")
private String password;
@Size(max = 20, message = "연락처는 최대 20자까지 입력해야 합니다.")
@NotBlank(message = "연락처는 필수 항목 입니다.")
private String phone;
}
@RestController
public class ApiMemberController {
@PostMapping("/api/member")
public ResponseEntity<?> addMember(@RequestBody @Valid MemberInput memberInput, Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) -> {
responseErrorList.add(ResponseError.of((FieldError) e));
});
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
return ResponseEntity.ok().build();
}
}
Q2) 사용자 정보를 입력받아서 저장하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
입력값: 이메일(유일한 값 확인), 이름, 비밀번호, 연락처, 가입일(현재일시)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String email;
@Column
private String memberName;
@Column
private String password;
@Column
private String phone;
@Column
private LocalDateTime regDate;
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/member")
public ResponseEntity<?> addMember(@RequestBody @Valid MemberInput memberInput, Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) -> {
responseErrorList.add(ResponseError.of((FieldError) e));
});
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
memberRepository.save(Member.builder()
.email(memberInput.getEmail())
.memberName(memberInput.getMemberName())
.password(memberInput.getPassword())
.phone(memberInput.getPhone())
.regDate(LocalDateTime.now())
.build());
return ResponseEntity.ok().build();
}
}
Q3) 사용자 정보를 수정하는 API를 다음 조건에 맞게 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
사용자 정보가 없는 경우 수정하는 API를 다음 조건에 맞게 작성해 보세요.
수정정보는 연락처만 수정가능, 수정일자는 현재 날짜
에러 메세지는 "사용자 정보가 없습니다"
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String email;
@Column
private String memberName;
@Column
private String password;
@Column
private String phone;
@Column
private LocalDateTime regDate;
@Column
private LocalDateTime updateDate;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberUpdate {
@Size(max = 20, message = "연락처는 최대 20자까지 입력해야 합니다.")
@NotBlank(message = "연락처는 필수 항목 입니다.")
private String phone;
}
public class MemberNotFoundException extends RuntimeException{
public MemberNotFoundException(String s){
super(s);
}
}
@RestControllerAdvice
public class MemberErrorHandler {
@ExceptionHandler(MemberNotFoundException.class)
public ResponseEntity<?> MemberNotFoundExceptionHandler(MemberNotFoundException e){
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PutMapping("/api/member/{id}")
public ResponseEntity<?> updateMember(@PathVariable Long id,
@RequestBody @Valid MemberUpdate memberUpdate,
Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) -> {
responseErrorList.add(ResponseError.of((FieldError) e));
});
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다"));
member.setPhone(memberUpdate.getPhone());
member.setUpdateDate(LocalDateTime.now());
memberRepository.save(member);
return ResponseEntity.ok().build();
}
}
Q4) 사용자 정보 조회(비밀번호, 가입일, 회원정보 수정일은 제외)의 기능을 수행하는 API를 작성해보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberResponse {
private Long id;
private String email;
private String memberName;
private String phone;
public static MemberResponse of(Member member) {
return MemberResponse.builder()
.id(member.getId())
.email(member.getEmail())
.memberName(member.getMemberName())
.phone(member.getPhone())
.build();
}
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@GetMapping("/api/member/{id}")
public MemberResponse getMember(@PathVariable Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
return MemberResponse.of(member);
}
}
Q5) 내가 작성한 공지사항 목록에 대한 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
삭제일과 삭제자 아이디는 보안상 내리지 않음
작성자 정보를 모두 내리지 않고, 작성자의 아이디와 이름만 내림
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Notice {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn
private Member member;
@Column
private String title;
@Column
private String contents;
@Column
private LocalDateTime regDate;
@Column
private LocalDateTime updateDate;
@Column
private int hits;
@Column
private int likes;
@Column
private boolean deleted;
@Column
private LocalDateTime deletedDate;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class NoticeResponse {
private Long id;
private Long regMemberId;
private String regMemberName;
private String title;
private String contents;
private LocalDateTime regDate;
private LocalDateTime updateDate;
private int hits;
private int likes;
public static NoticeResponse of(Notice notice) {
return NoticeResponse.builder()
.id(notice.getId())
.title(notice.getTitle())
.contents(notice.getContents())
.regDate(notice.getRegDate())
.regMemberId(notice.getMember().getId())
.regMemberName(notice.getMember().getMemberName())
.updateDate(notice.getUpdateDate())
.hits(notice.getHits())
.likes(notice.getLikes())
.build();
}
}
@Repository
public interface NoticeRepository extends JpaRepository<Notice, Long> {
Optional<List<Notice>> findByIdIn(List<Long> idList);
int countByTitleAndContentsAndRegDateIsGreaterThanEqual(String title, String contents, LocalDateTime regDate);
List<Notice> findByMember(Member member);
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
private final NoticeRepository noticeRepository;
@GetMapping("/api/member/{id}/notice")
public List<NoticeResponse> memberNotice(@PathVariable Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
List<Notice> noticeList = noticeRepository.findByMember(member);
List<NoticeResponse> noticeResponseList = new ArrayList<>();
noticeList.forEach((e) -> noticeResponseList.add(NoticeResponse.of(e)));
return noticeResponseList;
}
}
Q6) 사용자 등록시 이미 존재하는 이메일인 경우 예외를 발생시키는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
동일한 이메일에 가입된 회원 정보가 존재하는 경우 ExistsEmailException 발생
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
int countByEmail(String email);
}
public class ExistsEmailException extends RuntimeException {
public ExistsEmailException(String s) {
super(s);
}
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@ExceptionHandler(ExistsEmailException.class)
public ResponseEntity<?> ExistsEmailException(ExistsEmailException e) {
return new ResponseEntity<>(e.getMessage(),HttpStatus.BAD_REQUEST);
}
@PostMapping("/api/member")
public ResponseEntity<?> addMember(@RequestBody @Valid MemberInput memberInput, Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) -> responseErrorList.add(ResponseError.of((FieldError) e)));
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
if (memberRepository.countByEmail(memberInput.getEmail()) > 0) {
throw new ExistsEmailException("이미 존재하는 이메일 입니다.");
}
Member member = Member.builder()
.email(memberInput.getEmail())
.memberName(memberInput.getMemberName())
.password(memberInput.getPassword())
.phone(memberInput.getPhone())
.regDate(LocalDateTime.now())
.build();
memberRepository.save(member);
return ResponseEntity.ok().build();
}
}
Q7) 사용자 비밀번호를 수정하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
이전 비밀번호와 일치하는 경우 수정
일치하지 않는 경우 PasswordNotMatchException 발생
발생메세지는 "비밀번호가 일치하지 않습니다."
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MemberInputPassword {
@NotBlank(message = "현재 비밀번호는 필수 항목 입니다.")
private String password;
@Size(min = 4, max = 20, message = "비밀번호는 4~20사이의 길이로 입력해주세요.")
@NotBlank(message = "신규 비밀번호는 필수 항목 입니다.")
private String newPassword;
}
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
int countByEmail(String email);
Optional<Member> findByIdAndPassword(Long id, String password);
}
public class PasswordNotMatchException extends RuntimeException {
public PasswordNotMatchException(String s) {
super(s);
}
}
public class ApiMemberController {
private final MemberRepository memberRepository;
@PatchMapping("/api/member/{id}/password")
public ResponseEntity<?> updateMemberPassword(@PathVariable Long id,
MemberInputPassword memberInputPassword,
Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) ->
responseErrorList.add(ResponseError.of((FieldError) e)));
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
Member member = memberRepository.findByIdAndPassword(id, memberInputPassword.getPassword())
.orElseThrow(() -> new PasswordNotMatchException("비밀번호가 일치하지 않습니다."));
member.setPassword(memberInputPassword.getPassword());
memberRepository.save(member);
return ResponseEntity.ok().build();
}
@ExceptionHandler({ExistsEmailException.class, PasswordNotMatchException.class})
public ResponseEntity<?> ExistsEmailExceptionHandler(RuntimeException e) {
return new ResponseEntity<>(e.getMessage(),HttpStatus.BAD_REQUEST);
}
}
Q8) 회원가입시 비밀번호를 암호화하여 저장하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/member")
public ResponseEntity<?> addMember(@RequestBody @Valid MemberInput memberInput, Errors errors) {
List<ResponseError> responseErrorList = new ArrayList<>();
if (errors.hasErrors()) {
errors.getAllErrors().forEach((e) -> responseErrorList.add(ResponseError.of((FieldError) e)));
return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
}
if (memberRepository.countByEmail(memberInput.getEmail()) > 0) {
throw new ExistsEmailException("이미 존재하는 이메일 입니다.");
}
String encryptPassword = getEncryptPassword(memberInput.getPassword());
Member member = Member.builder()
.email(memberInput.getEmail())
.memberName(memberInput.getMemberName())
.password(encryptPassword)
.phone(memberInput.getPhone())
.regDate(LocalDateTime.now())
.build();
memberRepository.save(member);
return ResponseEntity.ok().build();
}
private String getEncryptPassword(String password) {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
return bCryptPasswordEncoder.encode(password);
}
}
Q9) 사용자 회원 탈퇴 기능에 대한 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
회원정보가 존재하지 않은 경우 예외처리
만약 사용자가 등록한 공지사항이 있는 경우는 회원삭제가 되지 않음
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberInputFind {
private String memberName;
private String phone;
}
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
int countByEmail(String email);
Optional<Member> findByIdAndPassword(Long id, String password);
Optional<Member> findByMemberNameAndPhone(String memberName, String phone);
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@DeleteMapping("/api/member/{id}")
public ResponseEntity<?> deleteMember(@PathVariable Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다"));
try {
memberRepository.delete(member);
} catch (DataIntegrityViolationException e) {
String message = "제약조건에 문제가 발생했습니다.";
return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
} catch (Exception e) {
String message = "회원 탈퇴 중 문제가 발생하였습니다.";
return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
}
return ResponseEntity.ok().build();
}
}
Q10) 사용자 아이디(이메일)을 찾는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
이름과 전화번호에 해당하는 이메일을 찾는다
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@GetMapping("/api/member/find")
public ResponseEntity<?> findMember(@RequestBody MemberInputFind memberInputFind) {
Member member = memberRepository
.findByMemberNameAndPhone(memberInputFind.getMemberName(), memberInputFind.getPhone())
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
MemberResponse memberResponse = MemberResponse.of(member);
return ResponseEntity.ok().body(memberResponse);
}
}
Q11) 비밀번호 초기화 요청(아이디 입력 후 전화번호로 문자 전송받음)을 수행하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
아이디에 대한 정보 조회 후
비밀번호를 초기화 후 이를 문자 전송 로직 호출
초기화 비밀번호는 문자열 10자로 설정
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@GetMapping("/api/member/{id}/password/reset")
public ResponseEntity<?> resetMemberPassword(@PathVariable Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
// 비밀번호 초기화
String resetPassword = getResetPassword();
String resetEncryptPassword = getEncryptPassword(resetPassword);
member.setPassword(resetEncryptPassword);
memberRepository.save(member);
String message = String.format("[%s]님의 임시 비밀번호가 [%s]로 초기화 되었습니다",
member.getMemberName(),resetPassword);
sendSMS(message);
return ResponseEntity.ok().build();
}
private String getResetPassword() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10);
}
void sendSMS(String message){
System.out.println("[문자메세지전송]");
System.out.println(message);
}
}
Q12) 내가 좋아요한 공지사항을 보는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class NoticeLike {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn
private Notice notice;
@ManyToOne
@JoinColumn
private Member member;
}
@Repository
public interface NoticeLikeRepository extends JpaRepository<NoticeLike, Long> {
List<NoticeLike> findByMember(Member member);
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
private final NoticeLikeRepository noticeLikeRepository;
@GetMapping("/api/member/{id}/notice/like")
public List<NoticeLike> likeNotice(@PathVariable Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
return noticeLikeRepository.findByMember(member);
}
}
사용자 인증 토큰 발행
Q1) 사용자 이메일과 비밀번호를 통해서 JWT을 발행하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
JWT 토큰 발행시 사용자 정보가 유요하지 않을 때 예외 발생
사용자정보가 존재하지 않는 경우(MemberNotFoundException) 예외 발생
비밀번호가 일치하지 않는 경우 PasswordNotMatchException 예외 발생
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberLogin {
@NotBlank(message = "이메일 항목은 필수 입니다.")
private String email;
@NotBlank(message = "비밀번호 항목은 필수 입니다.")
private String password;
}
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
int countByEmail(String email);
Optional<Member> findByIdAndPassword(Long id, String password);
Optional<Member> findByMemberNameAndPhone(String memberName, String phone);
Optional<Member> findByEmail(String email);
}
@UtilityClass
public class PasswordUtils {
// 입력한 패스워드를 해시된 패스워드랑 비교하는 함수
public static boolean equalPassword(String password, String encryptedPassword) {
return BCrypt.checkpw(password, encryptedPassword);
}
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/member/login")
public ResponseEntity<?> createToken(@RequestBody @Valid MemberLogin memberlogin) {
Member member = memberRepository.findByEmail(memberlogin.getEmail())
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
if(!PasswordUtils.equalPassword(memberlogin.getPassword(),member.getPassword())){
throw new PasswordNotMatchException("비밀번호가 일치하지 않습니다.");
}
return ResponseEntity.ok().build();
}
}
Q2) 사용자의 이메일과 비밀번호를 통해서 JWT을 발생하는 로직을 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberLoginToken {
private String token;
}
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/member/login")
public ResponseEntity<?> createToken(@RequestBody @Valid MemberLogin memberlogin) {
Member member = memberRepository.findByEmail(memberlogin.getEmail())
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
if(!PasswordUtils.equalPassword(memberlogin.getPassword(),member.getPassword())){
throw new PasswordNotMatchException("비밀번호가 일치하지 않습니다.");
}
// 토큰발행시점
String token = JWT.create()
.withExpiresAt(new Date()) //유효시간
.withClaim("member_id", member.getId())
.withSubject(member.getMemberName())
.withIssuer(member.getEmail())
.sign(Algorithm.HMAC512("zeroBase".getBytes()));
return ResponseEntity.ok().body(MemberLoginToken.builder().token(token).build());
}
}
Q3) JWT 토큰 발행시 발행 유효기간을 1개월로 저장하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/member/login")
public ResponseEntity<?> createToken(@RequestBody @Valid MemberLogin memberlogin) {
Member member = memberRepository.findByEmail(memberlogin.getEmail())
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다."));
if(!PasswordUtils.equalPassword(memberlogin.getPassword(),member.getPassword())){
throw new PasswordNotMatchException("비밀번호가 일치하지 않습니다.");
}
LocalDateTime expiredDateTime = LocalDateTime.now().plusMonths(1);
Date expiredDate = java.sql.Timestamp.valueOf(expiredDateTime);
String token = JWT.create()
.withExpiresAt(expiredDate) //유효시간
.withClaim("member_id", member.getId())
.withSubject(member.getMemberName())
.withIssuer(member.getEmail())
.sign(Algorithm.HMAC512("zeroBase".getBytes()));
return ResponseEntity.ok().body(MemberLoginToken.builder().token(token).build());
}
}
Q4) 이미 발행된 JWT 토큰을 통해서 토큰을 재발행하는 API를 작성해보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PatchMapping("/api/member/login")
public ResponseEntity<?> refreshToken(HttpServletRequest request) {
String token = request.getHeader("Z-TOKEN");
String email = "";
try {
email = JWT.require(Algorithm.HMAC512("zeroBase".getBytes()))
.build()
.verify(token)
.getIssuer();
} catch (SignatureVerificationException e) {
throw new PasswordNotMatchException("비밀번호가 일치하지 않습니다");
}
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new MemberNotFoundException("사용자 정보가 없습니다"));
LocalDateTime expiredDateTime = LocalDateTime.now().plusMonths(1);
Date expiredDate = java.sql.Timestamp.valueOf(expiredDateTime);
String newToken = JWT.create()
.withExpiresAt(expiredDate) //유효시간
.withClaim("member_id", member.getId())
.withSubject(member.getMemberName())
.withIssuer(member.getEmail())
.sign(Algorithm.HMAC512("zeroBase".getBytes()));
return ResponseEntity.ok().body(MemberLoginToken.builder().token(newToken).build());
}
}
Q5) JWT 토큰에 대한 삭제를 요청하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
@UtilityClass
public class JWTUtils {
private static final String KEY = "zeroBase";
public static String getIssuer(String token) {
return JWT.require(Algorithm.HMAC512(KEY.getBytes()))
.build()
.verify(token)
.getIssuer();
}
}
댓글남기기