[회원관리] 로그인
2023. 1. 3. 16:40ㆍ프로젝트/라이어게임
728x90
SMALL
로그인 API
기능 | Method | URL | Request | Response | 비고 |
로그인 | POST | /lier/login | { ”email”:”wlstpgns51@naver.com”, ”password”:”wls1234!” } |
data{ ”email”:””, ”nickname”:”” } + response |
1. POST 형식
2. Request 요청은 DTO 형식으로 이메일과 비밀번호 두가지만 필요하도록 했다.
3. Response 응답값은 json 형식으로 data 안에 로그인된 이메일과 닉네임이 반환 + Response에 토큰을 넣는다.
MemberController
// 로그인
@PostMapping(value = "/login")
public ResponseEntity<PrivateResponseBody> login(
@RequestBody LoginRequestDto requestDto,
HttpServletResponse response) {
log.info("로그인 - 아이디 : {}, 비밀번호 : {}", requestDto.getEmail(), requestDto.getPassword());
return memberService.login(requestDto, response);
}
- @RequestBody로 json 형태의 LoginRequestDto 이메일과 비밀번호를 넣어 Service단에 넘긴다.
- 로그인이 정상적으로 된다면 인증을 통해 Response 헤더에 토큰을 넣어서 반환하기 때문에 HttpServletResponse를 Service 단으로 넘긴다.
MemberService
// 로그인
@Transactional
public ResponseEntity<PrivateResponseBody> login(LoginRequestDto requestDto, HttpServletResponse response) {
// 로그인 시도한 이메일 아이디가 존재하는 아이디인지 확인 후 저장
Member member = isPresentMember(requestDto.getEmail());
// DB에 해당 아이디를 가진 멤버가 없다면 에러 처리
if (null == member) {
return new ResponseEntity<>(new PrivateResponseBody
(StatusCode.LOGIN_MEMBER_ID_FAIL, null), HttpStatus.BAD_REQUEST);
}
// 로그인 시도한 비밀번호를 인코딩하여 존재하는 비밀번호와 일치하는지 확인
if (!member.validatePassword(passwordEncoder, requestDto.getPassword())) {
return new ResponseEntity<>(new PrivateResponseBody
(StatusCode.LOGIN_PASSWORD_FAIL, null), HttpStatus.BAD_REQUEST);
}
//토큰 지급
TokenDto tokenDto = tokenProvider.generateTokenDto(member);
// response에 토큰을 담는다
tokenToHeaders(tokenDto, response);
// 전달드릴 내용이 매우 적기 때문에 굳이 Dto를 생성하지 않고 hashmap으로 전달
HashMap<String, String> login_info = new HashMap<>();
login_info.put("email", member.getEmail()); // 이메일
login_info.put("nickname", member.getNickname()); // 닉네임
log.info("액세스 토큰 : {}", response.getHeader("Authorization"));
log.info("리프레시 토큰 : {}", response.getHeader("Refresh-Token"));
// Message 및 Status를 Return
return new ResponseEntity(new PrivateResponseBody(StatusCode.LOGIN_OK, login_info), HttpStatus.OK);
}
- isPresentMember에 입력받은 이메일을 넣어 유저 정보를 불러온다.
- 유저 정보가 존재하지 않는다면 오류 처리를 한다.
- validatePassword 메소드에 passwordEncoder, 입력받은 비밀번호를 넣어 현재 불러온 유저 정보의 인코딩된 비밀번호와 입력받은 비밀번호가 매칭(matches())이 되는지 확인한다.
public boolean validatePassword(PasswordEncoder passwordEncoder, String password) {
return passwordEncoder.matches(password, this.password);
}
- TokenProvider의 GenerateTokenDto에 불러온 유저 정보를 넣어 AccessToken, RefreshToken을 만든다.
public TokenDto generateTokenDto(Member member) {
long now = (new Date().getTime());
Date accessTokenExpiresIn = new Date(now + ACCESS_TOKEN_EXPIRE_TIME);
String accessToken = Jwts.builder()
.setSubject(member.getEmail())
.claim(AUTHORITIES_KEY, Authority.ROLE_MEMBER.toString())
.setExpiration(accessTokenExpiresIn)
.signWith(key, SignatureAlgorithm.HS256)
.compact();
String refreshToken = Jwts.builder()
.setExpiration(new Date(now + REFRESH_TOKEN_EXPRIRE_TIME))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
RefreshToken refreshTokenObject = RefreshToken.builder()
.id(member.getMemberId())
.member(member)
.value(refreshToken)
.build();
refreshTokenRepository.save(refreshTokenObject);
return TokenDto.builder()
.grantType(BEARER_PREFIX)
.accessToken(accessToken)
.accessTokenExpiresIn(accessTokenExpiresIn.getTime())
.refreshToken(refreshToken)
.build();
}
- RefreshToken은 따로 RefreshToken Entity에 저장한다.
RefreshToken
package com.example.finalproject.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class RefreshToken extends Timestamped {
@Id
@Column(nullable = false)
private Long id;
@JoinColumn(name = "memberId", nullable = false)
@OneToOne(fetch = FetchType.LAZY)
private Member member;
@Column(nullable = false)
private String value;
}
- TokenDto에 생성한 토큰 정보들, 토큰 만료시간, 권한 정보를 builder로 대입하여 반환한다.
return TokenDto.builder()
.grantType(BEARER_PREFIX)
.accessToken(accessToken)
.accessTokenExpiresIn(accessTokenExpiresIn.getTime())
.refreshToken(refreshToken)
.build();
- 반환된 TokenDto와 HttpServletResponse를 tokentoHeaders 메소드에 넣어 Response에 토큰을 넣는다.
// response에 토큰을 담는다
tokenToHeaders(tokenDto, response);
- Response에 토큰을 넣어서 반환함과 동시에 로그인된 정보를 HashMap으로 반환하여 결과를 알려준다.
// 전달드릴 내용이 매우 적기 때문에 굳이 Dto를 생성하지 않고 hashmap으로 전달
HashMap<String, String> login_info = new HashMap<>();
login_info.put("email", member.getEmail()); // 이메일
login_info.put("nickname", member.getNickname()); // 닉네임
log.info("액세스 토큰 : {}", response.getHeader("Authorization"));
log.info("리프레시 토큰 : {}", response.getHeader("Refresh-Token"));
// Message 및 Status를 Return
return new ResponseEntity(new PrivateResponseBody(StatusCode.LOGIN_OK, login_info), HttpStatus.OK);
로그인이 정상적으로 되었다.
다음은 로그아웃을 정리해보자.
728x90
반응형
LIST
'프로젝트 > 라이어게임' 카테고리의 다른 글
[회원관리] 회원가입 (0) | 2022.12.30 |
---|---|
프로젝트 세팅 (0) | 2022.12.30 |
[회원관리] Jwt를 활용한 회원관리 기능 세팅 (0) | 2022.12.28 |
서비스 아키텍쳐 (0) | 2022.12.15 |