
Jwt와 Security 설정을 끝마쳤다. 전에 배운 내용이지만, 하나하나 구현하다 보니 어렵거나 헷갈리는 부분이 많았다.
이제 Jwt와 Security에 관한 내용들을 구현하고, 설정 하였으니 jwt를 이용한 회원가입과 로그인 기능을 RestApi로 구현해 볼 것입니다.
[회원가입과 로그인의 도메인은 sign-api로 통일 시켰습니다.]
public interface SignService {
SignUpResultDto SignUp(SIgnUpDto sIgnUpDto,String roles);
SignInResultDto SignIn(String email, String password);
}
@Service
public class SignServiceImpl implements SignService {
private Logger logger = LoggerFactory.getLogger(SignServiceImpl.class);
private JwtProvider jwtProvider;
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
@Autowired
public SignServiceImpl(UserRepository userRepository , JwtProvider jwtProvider,
PasswordEncoder passwordEncoder){
this.userRepository = userRepository;
this.jwtProvider = jwtProvider;
this.passwordEncoder = passwordEncoder;
}
@Override
public SignUpResultDto SignUp(SIgnUpDto signUpDto, String roles){
User user;
if(roles.equalsIgnoreCase("admin")){
user = User.builder()
.email(signUpDto.getEmail())
.password(passwordEncoder.encode(signUpDto.getPassword()))
.name(signUpDto.getName())
.roles(Collections.singletonList("ROLE_ADMIN"))
.build();
}else{
user = User.builder()
.email(signUpDto.getEmail())
.password(passwordEncoder.encode(signUpDto.getPassword()))
.name(signUpDto.getName())
.roles(Collections.singletonList("ROLE_USER"))
.build();
}
User saveduser = userRepository.save(user);
SignUpResultDto signUpResultDto = new SignUpResultDto();
logger.info("[getSignResultDto] User 정보 들어왔는지 확인 후 결과값 주입");
if(!saveduser.getEmail().isEmpty()){
setSucces(signUpResultDto);
}else{
setFail(signUpResultDto);
}
return signUpResultDto;
}
@Override
public SignInResultDto SignIn(String email,String password)throws RuntimeException{
User user = userRepository.getByEmail(email);
if(!passwordEncoder.matches(password, user.getPassword())){
throw new RuntimeException();
}
logger.info("[getSignInResult] 패스워드 일치");
logger.info("[getSignInResult] SignInResultDto 객체 생성");
SignInResultDto signInResultDto = SignInResultDto.builder()
.token(jwtProvider.createToken(String.valueOf(user.getEmail()),
user.getRoles()))
.build();
logger.info("[getSignInResult] SignInResultDto 객체에 값 주입");
setSucces(signInResultDto);
return signInResultDto;
}
private void setSucces(SignUpResultDto result){
result.setSuccess(true);
result.setCode(CommonResponse.SUCCESS.getCode());
result.setMsg(CommonResponse.SUCCESS.getMsg());
}
private void setFail(SignUpResultDto result){
result.setSuccess(true);
result.setCode(CommonResponse.Fail.getCode());
result.setMsg(CommonResponse.Fail.getMsg());
}
}
DTO값을 전달받아 값을 설정하는 CommonResponse클래스 생성, 회원가입, 로그인 값 전달 Dto 생성
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class SignUpResultDto {
private boolean success;
private int code;
private String msg;
}
@Data
@Getter
@Setter
public class SIgnUpDto {
private String email;
private String password;
private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class SignInResultDto extends SignUpResultDto{
private String token;
@Builder
public SignInResultDto(boolean success, int code, String msg, String token) {
super(success, code, msg);
this.token = token;
}
}
@RestController
@RequestMapping("/sign-api")
public class SignController {
private Logger logger = LoggerFactory.getLogger(SignController.class);
private SignService signService;
@Autowired
public SignController(SignService signService){
this.signService = signService;
}
@PostMapping("/sign-up")
public SignUpResultDto SignUp(@RequestBody SIgnUpDto signUpDto, String roles){
logger.info("[signUp] 회원가입을 수행합니다. id : {}, password : ****, name : {}, role : {}", signUpDto.getEmail(),
signUpDto.getPassword(),roles);
SignUpResultDto signUpResultDto = signService.SignUp(signUpDto,roles);
return signUpResultDto;
}
@PostMapping("/sign-in")
public SignInResultDto SignIn(@RequestParam String email, String password) {
logger.info("[sign-in] 로그인을 시도하고 있습니다. id : {}, password : *****", email);
SignInResultDto signInResultDto = signService.SignIn(email, password);
if(signInResultDto.getCode() == 0){
logger.info("[sign-in] 정상적으로 로그인이 되었습니다. id: {}, token : {}",email,signInResultDto.getToken());
signInResultDto.getToken();
}
return signInResultDto;
}
@GetMapping(value = "/exception")
public void exceptionTest()throws RuntimeException{
throw new RuntimeException("접근이 금지 되었습니다.");
}
@ExceptionHandler(value = RuntimeException.class)
public ResponseEntity<Map<String, String>> ExceptionHandler(RuntimeException e) {
HttpHeaders responseHeaders = new HttpHeaders();
//responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/json");
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
logger.error("ExceptionHandler 호출, {}, {}", e.getCause(), e.getMessage());
Map<String, String> map = new HashMap<>();
map.put("error type", httpStatus.getReasonPhrase());
map.put("code", "400");
map.put("message", "에러 발생");
return new ResponseEntity<>(map, responseHeaders, httpStatus);
}
}
-동작 시나리오-
1.회원가입 성공
2.회원가입을 성공한 계정을 바탕으로 로그인 -> 성공하면 Jwt 토큰 발급.
이전 포스트에서 설정한 스웨거를 이용하여 테스트를 할 예정이다.
http://localhost:8080/swagger-ui.html#/ -> 스웨거 URL
스웨거 주소로 들어가면 controller가 api문서로 자동화 되어 볼수 있다.

<회원가입 진행>

<회원가입 성공 response>

회원가입 한 정보를 가지고 로그인 진행.
<아이디, 비밀번호 입력>

<로그인 결과>

다음 포스트는 간단한 CRUD 게시판 RESTAPI에 회원가입 로그인을 합쳐보겠습니다.