1) service
AuthService
package clonestudy.clonestudy.login.service;
import clonestudy.clonestudy.exception.ShjException;
import clonestudy.clonestudy.login.dto.SignInRes;
import clonestudy.clonestudy.login.model.AccessToken;
import clonestudy.clonestudy.login.repository.TokenRepository;
import clonestudy.clonestudy.member.model.Member;
import clonestudy.clonestudy.share.LocalDateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AuthService {
@Autowired
private JwtService jwtService;
@Autowired
private TokenRepository tokenRepository;
public SignInRes createSignResponse(Member member) throws ShjException {
SignInRes signInRes = new SignInRes();
signInRes.setName(member.getName());
signInRes.setId(member.getId());
// 토큰 생성
String loginHashCode = LocalDateUtils.krNowByFormatter("yyyyMMddHHmmssSSS");
String accessToken = jwtService.createAccessToken(member.getId(), loginHashCode);
String refreshToken = jwtService.createRefreshToken(member.getId(), loginHashCode);
signInRes.setAccesstoken(accessToken);
signInRes.setRefreshtoken(refreshToken);
AccessToken accessToken1 = AccessToken.builder()
.accessToken(accessToken)
.build();
tokenRepository.save(accessToken1);
return signInRes;
}
}
JwtService
package clonestudy.clonestudy.login.service;
import clonestudy.clonestudy.exception.ShjException;
import clonestudy.clonestudy.login.dto.ValidateJwt;
import clonestudy.clonestudy.member.model.Member;
import clonestudy.clonestudy.share.LocalDateUtils;
import clonestudy.clonestudy.share.ResponseEnum;
import clonestudy.clonestudy.share.ResponseMessage;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import static org.springframework.jmx.export.naming.IdentityNamingStrategy.HASH_CODE_KEY;
@Component
@Slf4j
public class JwtService {
private static final String SECRET = "shj-admin";
private static final String ISSUER = "shj-admin";
private static final String ID_KEY = "id";
public static final long EXPIRED_MIN = 24 * 60;
public static final long REFRESH_EXPIRED_MIN = 24 * 60 * 7;
public String createAccessToken(int id, String hashCode) {
if (StringUtils.isBlank(hashCode)) {
return createAccessToken(
id, EXPIRED_MIN, LocalDateUtils.krNowByFormatter("yyyyMMddHHmmssSSS"));
}
return createAccessToken(
id, EXPIRED_MIN, hashCode);
}
public String createAccessToken(int id, long expiredMine, String hashCode) {
LocalDateTime now = LocalDateUtils.krNow().plusMinutes(expiredMine);
ZonedDateTime zonedDateTime = now.atZone(ZoneId.systemDefault());
return createAccessToken(id, zonedDateTime, hashCode);
}
/**
* 토큰 생성
* **/
private String createAccessToken(int encryptMemberId, ZonedDateTime zoneDateTime, String hashCode) {
try {
return JWT.create()
//토큰 발급자
.withIssuer(ISSUER)
//payload 작성, key - value
.withClaim(ID_KEY, encryptMemberId)
.withClaim(HASH_CODE_KEY, hashCode)
//토큰 만료날짜 지정
.withExpiresAt(Date.from(zoneDateTime.toInstant()))
//토큰 생성
.sign(Algorithm.HMAC256(SECRET));
} catch (JWTCreationException exception) {
return null;
}
}
public ValidateJwt verify(String accessToken) throws ShjException {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).withIssuer(ISSUER).build();
DecodedJWT decodedJWT = verifier.verify(accessToken);
return new ValidateJwt(decodedJWT.getClaim(ID_KEY).asString(), decodedJWT.getClaim(HASH_CODE_KEY).asString());
} catch (TokenExpiredException te) {
log.error("#### token expired ", te);
throw new ShjException(ResponseEnum.TOKEN_EXPIRED);
} catch (Exception e) {
log.error("#### token verify exception ", e);
throw new ShjException(ResponseEnum.AUTHENTIFICATION);
}
}
public String createRefreshToken(int id, String hashCode) {
if (StringUtils.isBlank(hashCode)) {
return createRefreshToken(
id, REFRESH_EXPIRED_MIN, LocalDateUtils.krNowByFormatter("yyyyMMddHHmmssSSS"));
}
return createRefreshToken(
id, REFRESH_EXPIRED_MIN, hashCode);
}
public String createRefreshToken(int id, long expiredMine, String hashCode) {
LocalDateTime now = LocalDateUtils.krNow().plusMinutes(expiredMine);
ZonedDateTime zonedDateTime = now.atZone(ZoneId.systemDefault());
return createRefreshToken(id, zonedDateTime, hashCode);
}
/**
* 토큰 생성
* **/
private String createRefreshToken(int encryptMemberId, ZonedDateTime zoneDateTime, String hashCode) {
try {
return JWT.create()
//토큰 발급자
.withIssuer(ISSUER)
//payload 작성, key - value
.withClaim(ID_KEY, encryptMemberId)
.withClaim(HASH_CODE_KEY, hashCode)
//토큰 만료날짜 지정
.withExpiresAt(Date.from(zoneDateTime.toInstant()))
//토큰 생성
.sign(Algorithm.HMAC256(SECRET));
} catch (JWTCreationException exception) {
return null;
}
}
}
LoginService
package clonestudy.clonestudy.login.service;
import antlr.Token;
import clonestudy.clonestudy.exception.ShjException;
import clonestudy.clonestudy.login.dto.SignInRes;
import clonestudy.clonestudy.login.model.AccessToken;
import clonestudy.clonestudy.login.model.LoginLog;
import clonestudy.clonestudy.login.repository.LoginLogRepository;
import clonestudy.clonestudy.login.repository.TokenRepository;
import clonestudy.clonestudy.login.vo.LoginLogVO;
import clonestudy.clonestudy.login.vo.LoginVO;
import clonestudy.clonestudy.login.vo.TokenVO;
import clonestudy.clonestudy.member.model.Member;
import clonestudy.clonestudy.member.repository.MemberRepository;
import clonestudy.clonestudy.share.LocalDateUtils;
import clonestudy.clonestudy.share.ResponseEnum;
import clonestudy.clonestudy.share.ResponseMessage;
import clonestudy.clonestudy.share.SHA256;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.NoSuchElementException;
@Service
@Slf4j
public class LoginService {
@Autowired
private LoginLogRepository loginLogRepository;
@Autowired
private MemberRepository memberRepository;
@Autowired
private AuthService authService;
@Autowired
private SHA256 sha256;
public ResponseEnum memberLog(LoginVO loginVO) throws NoSuchAlgorithmException {
Member member = memberRepository.findByEmail(loginVO.getEmail()).orElse(null);
if(member == null) {
return ResponseEnum.MIS_MATCH;
}
boolean pwdMatch = sha256.encrypt(loginVO.getPwd()).equals(member.getPwd());
if(!pwdMatch) {
return ResponseEnum.MIS_MATCH;
}
return ResponseEnum.SUCCESS;
}
public ResponseMessage memberLogin(LoginVO loginVO) throws NoSuchAlgorithmException, ShjException {
Member member = memberRepository.findByEmail(loginVO.getEmail()).orElse(null);
if(member == null) {
return new ResponseMessage(ResponseEnum.MIS_MATCH, null);
}
SignInRes signInRes = authService.createSignResponse(member);
boolean pwdMatch = sha256.encrypt(loginVO.getPwd()).equals(member.getPwd());
if(!pwdMatch) {
return new ResponseMessage(ResponseEnum.MIS_MATCH, null);
}
return new ResponseMessage(ResponseEnum.SUCCESS, signInRes);
}
public void saveLoginLog(String memberEmail, ResponseEnum responseEnum, String memberIP) {
LoginLog loginLog = LoginLog.builder()
.loginDateTime(LocalDateTime.now())
.memberEmail(memberEmail)
.statusCode(String.valueOf(responseEnum.getStatusCode()))
.statusCodeName(responseEnum.name())
.statusMessage(responseEnum.getMessage())
.memberIP(memberIP)
.build();
loginLogRepository.save(loginLog);
}
public List<LoginLog> findLoginLogList(LoginLogVO loginLogVO) {
String memberEmail = loginLogVO.getMemberEmail();
memberRepository.findByEmail(memberEmail).orElseThrow( () -> new NoSuchElementException(ResponseEnum.MIS_MATCH.getMessage()));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startDateTime = LocalDateTime.parse(loginLogVO.getFirstDateTime(), dateTimeFormatter);
LocalDateTime endDateTime = LocalDateTime.parse(loginLogVO.getEndDateTime(), dateTimeFormatter);
return loginLogRepository.findAllByLoginDateTimeBetweenAndMemberEmailContaining(startDateTime, endDateTime, memberEmail);
}
public void updateMemberLoginData(String memberEmail, ResponseEnum responseEnum) {
LocalDateTime now = LocalDateTime.now();
Member member = memberRepository.findByEmail(memberEmail).orElseThrow( () -> new NoSuchElementException(ResponseEnum.MIS_MATCH.getMessage()));
//로그인 시간 set
if(member.getFirstLogin() == null) {
member.setFirstLogin(now);
} else {
member.setLastLogin(now);
}
//로그인 횟수 set
if(responseEnum.getStatusCode() == 200) {
member.setLoginCount(member.getLoginCount() + 1);
member.setLoginFailCount(0);
} else {
member.setLoginFailCount(member.getLoginFailCount() + 1);
}
memberRepository.save(member);
}
}
2) repository
LoginLogRepository
package clonestudy.clonestudy.login.repository;
import clonestudy.clonestudy.login.model.LoginLog;
import clonestudy.clonestudy.login.model.LoginLog.ID;
import org.springframework.data.jpa.repository.JpaRepository;
import java.time.LocalDateTime;
import java.util.List;
public interface LoginLogRepository extends JpaRepository<LoginLog, ID> {
List<LoginLog> findAllByLoginDateTimeBetweenAndMemberEmailContaining(LocalDateTime startDateTime, LocalDateTime endDateTime, String memberEmail);
LoginLog findByMemberEmail(String memberEmail);
}
'개발이 좋아서 > Spring이 좋아서' 카테고리의 다른 글
[Backend] - 로그인 및 회원가입(회원가입_service, repository) (0) | 2022.10.25 |
---|---|
[Backend] - 로그인 및 회원가입(로그인_dto, model, vo) (0) | 2022.10.25 |
[Backend] - 로그인 및 회원가입(swagger, share) (0) | 2022.10.25 |
회원 관리 예제 - 웹 MVC 개발 (0) | 2022.10.07 |
회원관리 예제 - 스프링 빈과 의존관계 (0) | 2022.10.07 |