- 로그인은 post일까 Get일까?
로그인은 사용자가 입력했을 때, 보내는거니까 post!- loginRequest에는 뭐가 들어갈까?
요청 줄 값은 로그인 정보인 아이디, 비밀번호를 준다.
1) LoginRequest
public record LoginRequest(
String userId,
String password
) {
}
2) controller
@PostMapping("/login")
public void login(@RequestBody LoginRequest loginRequest){
userService.login(loginRequest);
}
3) service
쿼리메서드를 작성해서 아이디(UserId)를 찾는 함수를 작성해준다.
//repository에 작성
UserInfo findByUserId(String userId);
public void login(LoginRequest loginRequest) {
//a)
UserInfo user = userRepository.findByUserId(loginRequest.userId());
//b)
if(!user == null)){ // user자체에 지금 UserId를 찾아왔으니까 '!user.getUserId().equals(loginRequest.userId())'를 할 필요가 없는 것
}
throw new NoSuchElementException("아이디, 비밀번호가 틀렸습니다.");
}
if (!SecurityUtils.sha256EncryptBase64(loginRequest.password()).equals(user.getPassWord())){
throw new NoSuchElementException("아이디, 비밀번호가 틀렸습니다.");
}
}
SecurityUtils.sha256EncryptBase64 -> 비밀번호 해쉬화
데이터에 들어있는 비밀번호는 한번 해쉬화를 했기 때문에 해쉬화를 하지 않은 request의 데이터들을 그냥 비교하면 당연히! 다르다고 한다. 따라서 요청이 들어온 request를 해쉬화로 바꿔줘야한다.
비밀번호를 그냥 노출하는건 굉장히 위험하기 때문에 알아보기 어렵게 코드화같이 문자를 다르게 바꿔두는 것이다. 대문자로만 바꿔도 해쉬는 완전히 달라진다.
로그인이 잘 동작하는지 테스트를 진행한다.
@Test
void 로그인테스트() {
UserResponse 사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "abcABC123!!!", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new LoginRequest("chuchu", "abcABC123!!!"))
.when()
.post("/login")
.then().log().all()
.statusCode(200);
}
로그인은 내가 그 사용자라는
증표(증거)가 필요하다. 그걸 토큰이라 부른다.
토큰을 만들어서 서버에 전송해줘야 내가 이 사용자라는 것을 알려주게 된다.
1) Response에 token을 하나 내보내준다.
public record LoginResponse(
String token
) {
}
2) controller에 loginResponse로 output값을 바꿔준다.
//로그인 API
@PostMapping("/login")
public LoginResponse login(@RequestBody LoginRequest loginRequest){
return userService.login(loginRequest);
}
3) service
Jwtprovider를 하나 만들어주고, 그 곳에서 토큰을 생성해주는 함수를 만들어준다. 그걸 가져오기만 하면된다.
public LoginResponse login(LoginRequest loginRequest) {
UserInfo user = userRepository.findByUserId(loginRequest.userId());
if(!user.getUserId().equals(loginRequest.userId())){
throw new NoSuchElementException("아이디, 비밀번호가 틀렸습니다.");
}
if (!SecurityUtils.sha256EncryptBase64(loginRequest.password()).equals(user.getPassWord())){
throw new NoSuchElementException("아이디, 비밀번호가 틀렸습니다.");
}
return new LoginResponse(jwtProvider.createToken(loginRequest.userId()));
}
토큰 생성 테스트
@Test
void 로그인테스트() {
UserResponse 사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "abcABC123!!!", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
LoginResponse token = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new LoginRequest("chuchu", "abcABC123!!!"))
.when()
.post("/login")
.then().log().all()
.statusCode(200)
.extract()
.as(LoginResponse.class);
assertThat(token).isNotNull();
}
테스트도 잘 통과하는 것을 확인하였다.
🔺쿠키랑 토큰을 쓰면 로그인을 했다는걸 어케 알지요?
-> 쿠키나 토큰은 로그인했다는 증거를 유저가 가지고 있는 것이다. 매번 id, 비밀번호를 주지 않아도 증거만 있으면 된다.
😐 느낀점
로그인을 구현할 때 가장 중요한 2가지가 있다.
1. 해쉬화되어 있는 상태의 비밀번호를 해쉬화가 안된 비밀번호와 비교하면 안된다.
2. 로그인은 내가 이 계정의 사용자라는 것을 알 수 있는 증표(증거)가 꼭! 필요하다
-> 그것이 바로 토큰! 토큰이 있어야 계정에 들어갈 수 있다.