zoaseo
To Infinity And Beyond
zoaseo
전체 방문자
오늘
어제
  • 분류 전체보기 (760)
    • 개발이 좋아서 (378)
      • Java가 좋아서 (42)
      • Spring이 좋아서 (50)
      • JPA가 좋아서 (0)
      • QueryDSL이 좋아서 (26)
      • Docker가 좋아서 (7)
      • Redis가 좋아서 (7)
      • AWS가 좋아서 (5)
      • CI/CD가 좋아서 (6)
      • Troubleshooting이 좋아서 (4)
      • Kotlin이 좋아서 (7)
      • SQL이 좋아서 (6)
      • HTTP가 좋아서 (21)
      • JavaScript가 좋아서 (30)
      • TypeScript가 좋아서 (6)
      • Vue가 좋아서 (21)
      • Flutter가 좋아서 (61)
      • React가 좋아서 (20)
      • Redux(React)가 좋아서 (2)
      • Angular가 좋아서 (22)
      • HTML이 좋아서 (9)
      • CSS가 좋아서 (15)
      • PHP가 좋아서 (9)
      • Illustrator가 좋아서 (2)
    • 노력이 좋아서 (169)
    • 결과물이 좋아서 (14)
    • 코딩연습이 좋아서 (78)
      • 이론이 좋아서 (62)
      • SQL이 좋아서 (0)
    • 유용한 사이트가 좋아서 (28)
    • Github (2)

인기 글

티스토리

hELLO · Designed By 정상우.
zoaseo

To Infinity And Beyond

개발이 좋아서/Spring이 좋아서

[Backend] - 로그인 및 회원가입(로그인_service, repository)

2022. 10. 25. 14:25

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

    티스토리툴바