안녕하세요 보라입니다😀 벌써 UMC 강의의 마지막 주차가 되었네요!
바로 시작하겠습니다!
- 실습 과정
- 트러블 슈팅
- 강의 후기
이번에는 jwt를 이용하여 로그인 API를 만들어보겠다!
먼저 PostLoginReq
와 PostLoginRes
모델을 만들어주자.
//PostLoginReq
@Getter
@Setter
@AllArgsConstructor
public class PostLoginReq {
private String email;
private String pwd;
}
//PostLoginRes
@Getter
@Setter
@AllArgsConstructor
public class PostLoginRes {
private int userIdx;
private String jwt;
}
//UserController
@ResponseBody
@PostMapping("/login")
public BaseResponse<PostLoginRes> logIn(@RequestBody PostLoginReq postLoginReq) {
try{
//email 입력이 되었는지 확인
if(postLoginReq.getEmail() == null) {
return new BaseResponse<>(POST_USERS_EMPTY_EMAIL);
}
//pwd 입력이 되었는지 확인
if(postLoginReq.getPwd() == null) {
return new BaseResponse<>(POST_USERS_EMPTY_PASSWORD);
}
//email 정규식 검증
if(!isRegexEmail(postLoginReq.getEmail())) {
return new BaseResponse<>(POST_USERS_INVALID_EMAIL);
}
PostLoginRes postLoginRes = userService.logIn(postLoginReq);
return new BaseResponse<>(postLoginRes);
} catch(BaseException exception){
return new BaseResponse<>((exception.getStatus()));
}
}
//UserDAO
public User getPwd(PostLoginReq postLoginReq) {
String getPwdQuery = "SELECT userIdx, name, nickName, email, pwd from User where email = ?";
String getPwdParams = postLoginReq.getEmail();
return this.jdbcTemplate.queryForObject(getPwdQuery,
(rs,rowNum)-> new User (
rs.getInt("userIdx"),
rs.getString("name"),
rs.getString("nickName"),
rs.getString("email"),
rs.getString("pwd")
),
getPwdParams
);
}
//UserService
public PostLoginRes logIn(PostLoginReq postLoginReq) throws BaseException {
User user = userDao.getPwd(postLoginReq);
String encryptPwd;
try{
//비밀번호 암호화
encryptPwd = new SHA256().encrypt(postLoginReq.getPwd());
} catch(Exception exception){
throw new BaseException(PASSWORD_ENCRYPTION_ERROR);
}
//암호화된 비밀번호와 비교
if(user.getPwd().equals(encryptPwd)) {
int userIdx = user.getUserIdx();
String jwt = jwtService.createJwt(userIdx);
return new PostLoginRes(userIdx, jwt);
}
else {
throw new BaseException(FAILED_TO_LOGIN);
}
}
JWT_SECRET_KEY
라는 것이 있다. 현재는 config.secret 경로에 임의로 암호화 KEY가 작성되어 있고 이 KEY는 절대 노출되면 안된다! 깃허브에 올릴 때도 조심하도록 하자~ public String createJwt(int userIdx){
Date now = new Date();
return Jwts.builder()
.setHeaderParam("type","jwt")
.claim("userIdx",userIdx)
.setIssuedAt(now)
.setExpiration(new Date(System.currentTimeMillis()+1*(1000*60*60*24*365)))
.signWith(SignatureAlgorithm.HS256, Secret.JWT_SECRET_KEY)
.compact();
}
POSTMAN에서 jwt 로그인 테스트를 해보기 전에, 비밀번호가 암호화 된 계정이 하나 있어야 하므로 회원가입을 진행해주었다.
그리고 테스트를 해보았다.
성공!
//PostController
@ResponseBody
@PostMapping("")
public BaseResponse<PostPostsRes> createPost(@RequestBody PostPostsReq postPostsReq) {
try{
//*****여기부터 추가된 코드*****
//jwt
int userIdxByJwt = jwtService.getUserIdx();
//맞는지 검증
if(postPostsReq.getUserIdx() != userIdxByJwt) {
return new BaseResponse<>(BaseResponseStatus.INVALID_USER_JWT);
}
//*****여기까지 추가된 코드*****
//게시물 본문의 길이가 너무 길 때
if(postPostsReq.getContent().length() > 450) {
return new BaseResponse<>(BaseResponseStatus.POST_POSTS_INVALID_CONTENTS);
}
//사진이 선택되지 않았을 때
if(postPostsReq.getPostImgUrls().size() < 1) {
return new BaseResponse<>(BaseResponseStatus.POST_POSTS_EMPTY_IMGURL);
}
PostPostsRes postPostsRes = postService.createPost(postPostsReq.getUserIdx(), postPostsReq);
return new BaseResponse<>(postPostsRes);
} catch(BaseException exception){
return new BaseResponse<>((exception.getStatus()));
}
}
저번 주차에 만들었던 게시물 생성 API 코드를 다시 테스트해보자!
위와 같이 jwt를 입력하라고 뜬다.
위처럼 헤더에 jwt 키를 추가해주었다.
그러면 Body result에서는 null이라고 뜨긴 하는데, db로 들어가보면 요청이 잘 수행되었다!
아래는 Post 테이블이고, 가장 아래에 방금 만든 게시물 데이터가 생겼다 ㅎㅅㅎ
방금 테스트를 할 때 jwt 값을 살짝 바꿔주었을 때는 유효하지 않는 jwt라고 뜬다.
구현 성공!
jwt 로그인 테스트를 위해 회원가입을 하려고 했는데 에러가 발생했다.
알고 보니, 내 DB에서는 column을 pwd라고 만들어주었는데 여기저기서 password와 pwd를 번갈아 사용하다보니 헷갈린 거였다! password를 pwd라고 고쳐주었다.
그랬더니...
아래 코드에서 에러가 난 것 같았다.
알고보니 pwd가 그대로 db에 들어가는 것이 아니라, 암호화 처리가 되어서 엄청 길게 들어가기 때문에 내 db에 설정되어있는 pwd varchar(20) 가지고는 택도 없었던 것이었다. pwd의 타입을 TEXT로 수정해주니 해결되었다!
한 학기 동안 많은 걸 하려고 욕심을 냈다 보니, 조금 버거운 적도 있었던 것 같다. 학교 강의들(3학년이다보니 전공도 많이 듣고 과제도 많았는데 그나마 듣는 교양도 수학이라서...), 학생회 집부 활동, UMC 강의 그리고 주짓수까지.. 솔직히 주짓수에 가장 열심히 임한 것 같다 ㅋㅋㅋㅋ 공부도 중간고사 때까지는 열심히 했는데 그 이후로 의욕을 잃은 듯하다...^^
그리고 Spring boot를 처음 다루어 보는데 좋은 강의를 만나서 정말 의미있는 경험이었고, 이 지식들을 바탕으로 더 쉽게 웹 개발을 할 수 있을 것 같다. 내 자신에게 솔직해지자면 최선을 다하지 못한 주차도 있었고, 에러 해결도 못해서 계속 다음 주로 다다음 주로 미루기도 했지만, 모든 경험들이 다 다음 프로젝트 때 거름이 될 것 같다!!