인프라 감자 2022. 12. 14. 01:36

유저를 관리하기 위해 구현해야 할 API는 유저를 추가하는 회원가입, 로그인, 유저 정보 수정, 유저 정보 보기 등이 있을 수 있다. 스프링 부트로 RDS와 연동해 RestAPI를 구현해볼려고 한다.

 

API 구현하기 전 준비 단계

model package

  • GetUserRes : 유저 정보를 출력
  • PostUserReq : 유저를 입력하기 위한 request
  • PostUserRes : 유저를 입력하고 결과를 출력하기 위한 result
  • User : 유저 관리

utils package

  • validationRegex : validation을 관리하기 위핸 만든 페이지이다.
package com.example.delivery.src.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidationRegex {
//이메일 형식을 체크하기 위한 코드
    public static boolean isRegexEmail(String target) {
        String regex = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$";
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(target);
        return matcher.find();
    }
}
  • JwtService : 비밀번호를 JWT로 관리하기 위해 만들었다. 비밀번호를 암호화 할 것이다.
public String createJwt(int userIdx){ //유저 인덱스로 생성
        Date now = new Date(); 
        return Jwts.builder()
                .setHeaderParam("type","jwt") //type 설정
                .claim("userIdx",userIdx) // Payload에 담길 데이터
                .setIssuedAt(now) //발급 시간
                .setExpiration(new Date(System.currentTimeMillis()+1*(1000*60*60*24*365))) //만료 시간
                .signWith(SignatureAlgorithm.HS256, Secret.JWT_SECRET_KEY) //서명 알고리즘과 비밀 키
                .compact(); //JWT 토큰 생성
    }
    
    public String getJwt(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        return request.getHeader("X-ACCESS-TOKEN");
    }
    
    public int getUserIdx() throws BaseException {

        //1. JWT 추출
        String accessToken = getJwt();
        if(accessToken == null || accessToken.length() == 0){
            throw new BaseException(EMPTY_JWT);
        }

        // 2. JWT parsing
        Jws<Claims> claims;
        try{
            claims = Jwts.parser()
                    .setSigningKey(Secret.JWT_SECRET_KEY)
                    .parseClaimsJws(accessToken);
        } catch (Exception ignored) {
            throw new BaseException(INVALID_JWT);
        }

        // 3. userIdx 추출
        return claims.getBody().get("userIdx",Integer.class);  // jwt 에서 userIdx를 추출합니다.
    }
  • AES128 : AES 뒤에 붙는 128이나 192, 256은 대칭키의 bit수를 나타내는 것으로  AES-128의 경우 128bit의 대칭키를 쓰는 암호화 알고리즘이다.
package com.example.demo.utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;

public class AES128 {
    private final String ips;
    private final Key keySpec;

    public AES128(String key) {
        byte[] keyBytes = new byte[16];
        byte[] b = key.getBytes(UTF_8);
        System.arraycopy(b, 0, keyBytes, 0, keyBytes.length);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        this.ips = key.substring(0, 16);
        this.keySpec = keySpec;
    }
    //암호화 관련 함수
    public String encrypt(String value) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ips.getBytes()));
        byte[] encrypted = cipher.doFinal(value.getBytes(UTF_8));
        return new String(Base64.getEncoder().encode(encrypted));
    }
    //복호화 관련함수
    public String decrypt(String value) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ips.getBytes(UTF_8)));
        byte[] decrypted = Base64.getDecoder().decode(value.getBytes());
        return new String(cipher.doFinal(decrypted), UTF_8);
    }
}