//로그인
@PostMapping("/user/login")
public ApiResponse login(@RequestBody Map<String, String> user, HttpServletResponse response) {
if (empty(userMapper.getUser(user.get("id")))) {
throw new IllegalStateException("아이디 또는 비밀번호가 맞지 않습니다");
}
User user2 = userMapper.getUser(user.get("id"));
if (!passwordEncoder.matches(user.get("password"), user2.getPassword())) {
throw new IllegalStateException("아이디 또는 비밀번호가 맞지 않습니다");
}
userService.login(user2, response);
return ApiResponse.createSuccessWithNoContent();
}
authenticationManagerBuilder.getObject()의 authenticate함수를 사용하여 사용자 인증을 진행한다.{
"status": "error",
"data": null,
"message": "사용자 계정이 잠겨 있습니다"
}
UserDetails인터페이스 를 구현는 User클래스@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
isAccountNonExpired() : 계정의 만료 여부를 반환합니다.
isAccountNonLocked() : 계정이 잠겨 있는지 여부를 반환합니다.
isCredentialsNonExpired() : 사용자 자격 증명(비밀번호 등)의 만료 여부를 반환합니다.
isEnabled() : 계정의 활성화 여부를 반환합니다.
이러한 메소드를 적절히 구현하여 보안을 강화할 수 있다.
보안 메소드를 사용하지 않는 경우는 true로 return
왜냐하면, check 함수로 true인지 false인지 체크해 false이면 오류를 발생시킨다.
private class DefaultPreAuthenticationChecks implements UserDetailsChecker {
@Override
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
AbstractUserDetailsAuthenticationProvider.this.logger
.debug("Failed to authenticate since user account is locked");
throw new LockedException(AbstractUserDetailsAuthenticationProvider.this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"));
}
if (!user.isEnabled()) {
AbstractUserDetailsAuthenticationProvider.this.logger
.debug("Failed to authenticate since user account is disabled");
throw new DisabledException(AbstractUserDetailsAuthenticationProvider.this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
}
if (!user.isAccountNonExpired()) {
AbstractUserDetailsAuthenticationProvider.this.logger
.debug("Failed to authenticate since user account has expired");
throw new AccountExpiredException(AbstractUserDetailsAuthenticationProvider.this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"));
}
}
}
//로그인
@PostMapping("/user/login")
public ApiResponse login(@RequestBody Map<String, String> user, HttpServletResponse response) {
userService.login(user, response);
return ApiResponse.createSuccessWithNoContent();
}
//로그인
public void login(Map user, HttpServletResponse response){
// 1. Login ID/PW 를 기반으로 Authentication 객체 생성
// 이때 authentication 는 인증 여부를 확인하는 authenticated 값이 false
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.get("id"), user.get("password"));
// 2. 실제 검증 (사용자 비밀번호 체크)이 이스프링 부트 내부 함수 코드 보기루어지는 부분
// authenticate 매서드가 실행될 때 CustomUserDetailsService 에서 만든 loadUserByUsername 메서드가 실행
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
System.out.println("autentication " + authentication);
String accessToken = jwtTokenProvider.createToken(authentication.getName(), authentication.getAuthorities().toString());
String refreshToken = jwtTokenProvider.createRefreshToken(authentication.getName(), authentication.getAuthorities().toString());
jwtTokenProvider.setHeaderAccessToken(response, accessToken);
userMapper.saveRefreshToken(refreshToken, authentication.getName());
}