728x90

AWS EC2는 일래스틱 컴퓨트 클라우드

AWS 서비스형 인프라스트럭처

Virtual machine 로드 밸런서 오토스케일링 ASG ELB EBS

 

EC2 SIzing & configure service

OS : Linux window maxos

CPU

RAM
Storage space

EBS & EFS NETWORK attached

EC2 insatance Store

방화벽 규칙

 

EC2 User data

 

사용자 데이터 스크립트를 사용하여 인스턴스를 부트스트래핑

부트스트래핑은 머신이 작동될때 명령을 시작

부팅 작업을 자동화

업데이트 소프트웨어 설치 다운로드

루트계정 실행

sudo

 

인스턴스 타입

t2.micro

스토리지 온리 EBS

t2.xlarge 

c5d.4xlarge

 

프리티어 

t2.micro

750h / 1m

 

 

728x90

'project > aws' 카테고리의 다른 글

[AWS] 예산 설정  (0) 2024.05.24
[AWS] TIL 2024-05-22  (0) 2024.05.22
[AWS] 계정 만들기  (0) 2022.07.22
728x90

무료 프리티어사용량을 초과해 $0.01 요금이 발생할 경우 예산을 초과했다고 알려주는 서비스

728x90

'project > aws' 카테고리의 다른 글

[AWS] 2024-05-24 EC2  (0) 2024.05.24
[AWS] TIL 2024-05-22  (0) 2024.05.22
[AWS] 계정 만들기  (0) 2022.07.22
728x90

IAM 자격증명

 

IAM Credential Report (Account level)

IAM 자격증명 보고서 계정 수준에서 다양한 사용자와 다양한 자격증명 상태 포함

 

 

IAM Access Advisor (User level)

IAM 엑세스 관리자 사용자 수준에서 가능

사용자에게 부여된 서비스 권한 해당 서비스에 마지막으로 접근한 시간

최소권한의 원칙에 따랐을 때

매우 도움 되는 정보입니다

해당 도구를 사용하여 어떤 권한이 사용되지 않는지 볼 수 있고

따라서 사용자의 권한을 줄여

최소권한의 원칙을 지킬 수 있습니다

 

 

 

IAM Guide Line

루트 계정은 AWS 계정을 설정할때를 제외하고 사용 X

하나의 AWS 사용자는 한면의 실제 사용자 의미

사용자가 추가될 경우 새로운 사용자를 만들어서 제공

그룹 수주 보안 관리

비밀번호 정책을 강력하게

 

권한을 부여 할때는 역할을 만들어서 부여

AWS 프로그래밍의 경우 CLI나 SDK 사용

액세스키 만들기 (반드시) - 비밀번호와 같음

계정 권한 감사는 IAM 자격 증명 보고서와 IAM 엑세스 분석기를 사용 가능

IAM 사용자와 액세스 키 공유 X

728x90

'project > aws' 카테고리의 다른 글

[AWS] 2024-05-24 EC2  (0) 2024.05.24
[AWS] 예산 설정  (0) 2024.05.24
[AWS] 계정 만들기  (0) 2022.07.22
728x90

[관리자 페이지] 암호화 유틸리티 만들기



    // https://mvnrepository.com/artifact/org.mindrot/jbcrypt
    implementation group: 'org.mindrot', name: 'jbcrypt', version: '0.4'

Bcrypt 를 사용하기 위한 dependency 추가 !

package com.hiio.adminserver.utils;

import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

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;

@Component
public class CryptoUtil {

    public String encrypt(String value) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Key key = this.getKey();
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(key.toString().substring(0, 16).getBytes()));
        return new String(Base64.getEncoder().encode(cipher.doFinal(value.getBytes())));
    }

    public String decrypt(String encryptValue) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Key key = this.getKey();
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(key.toString().substring(0, 16).getBytes()));

        return new String(cipher.doFinal(Base64.getDecoder().decode(encryptValue)));
    }

    public String bcrypt(String value){
        return  BCrypt.hashpw(value,BCrypt.gensalt());
    }

    public boolean validBcrypt(String value,String hashedValue){
        return BCrypt.checkpw(value,hashedValue);
    }


    public Key getKey() {
        return "12345678901234567890123456789012";

    }


}

메소드 생성

encrypt | decrypt | bcrypt | validBcrypt |
양방향암호화 | 복호화 | 단방향암호화 | 검증 |

AES/CBC/PKCS5Padding 알고리즘 사용

양방향 암호화의 경우 개인정보(이메일, 휴대폰 번호 등)이나 암호화가 필요한 정보를 DB에 저장 시 암호화해서 저장 하기 위해 사용
단방향 암호화의 경우 비밀번호 암호화에 사용

static 키워드를 사용한 객체 사용보다는 @Component 를 통해 Bean 등록 사용

// Crypto Util Test Code

package com.hiio.adminserver.utils;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class CryptoUtilTest {
    private final Logger log = LoggerFactory.getLogger(getClass());
    @Autowired
    private CryptoUtil cryptoUtil;
    @Test
    public void encrypt(){
        try{
            String value = "test@test.com";
            String encrypted = cryptoUtil.encrypt(value);
            log.info(encrypted);
        }catch(Exception e){
            log.error(e.getMessage());
        }
    }


    @Test
    public void decrypt(){
        try{
            String value = "4pzZnfHbutpNFvnWISGfzA==";
            String decrypted = cryptoUtil.decrypt(value);
            log.info(decrypted);
        }catch(Exception e){
            log.error(e.getMessage());
        }
    }

    @Test
    public void bcrypt(){
        String value="password";
        String bcrypted = cryptoUtil.bcrypt(value);
        log.info(bcrypted);
    }

    @Test
    public void validBcrypt(){
        String bcrypted = "$2a$10$jqOVKXzru5.okuYI8A13HeGvxZv3Zt9rVliaFLegTcamh6u4GTzU2";
        String plain = "password";
        boolean valided = cryptoUtil.validBcrypt(plain,bcrypted);
        Assertions.assertTrue(valided);


    }
}
728x90
728x90

DTO (Data Transfer Object)

계층간 데이터 교환에 쓰이는 객체이다.
Controller <-> Service <-> DAO <-> DB

package com.hiio.adminserver.dto.user;

import com.hiio.adminserver.entity.user.UserEntity;
import jakarta.validation.constraints.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class UserDTO {


    private String email;
    private String password;
    private String name;


    public static UserDTO of(UserEntity user) {
        return UserDTO
                .builder()
                .email(user.getEmail())
                .password(user.getPassword()
                .name(user.getName())
                .build();
    }

    public UserEntity toEntity(){
        return UserEntity.builder().email(email).password(password).name(name).build();
    }
}
728x90
728x90

먼저 UserEntity를 정의 합니다.

package com.hiio.adminserver.entity.user;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.*;

@Entity
@Table(name = "T_USER")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserEntity {

    @Id
    @Column(name = "USER_EMAIL", length = 512)
    private String email;

    @Column(name = "USER_PASSWORD", length = 64, nullable = true)
    private String password;

    @Column(name = "USER_NAME", length = 64, nullable = true)
    private String name;
}

Email 을 id로 하고 512의 길이를 가집니다.
password는 null이 들어 올 수 있고 길이는 64입니다.
name 은 비밀번호와 마찬가지로 null을 허용하고 길이는 64입니다.

추후에 속성들이 추가 되거나 수정할 예정입니다.

그럼 이제 Repository를 하나 만들어 줍니다.

package com.hiio.adminserver.repository.user;

import com.hiio.adminserver.entity.user.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
}

그리고 총 3개의 insert 테스트 코드를 작성해 줬습니다.

  1. 아무런 속성값을 입력하지 않으면 JpaSystemException이 발생하는 것이 예상값 테스트
  2. 이메일 속성값에 빈문자열을 입력했을 경우 TransactionSystemException이 발생하는 것이 예상값인 테스트
  3. 이메일 속성값만을 넣은 테스트 코드

package com.hiio.adminserver.User;


import com.hiio.adminserver.entity.user.UserEntity;
import com.hiio.adminserver.repository.user.UserRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
class UserRepositoryTest {
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserRepository userRepo;

    @Test
    @DisplayName("Insert User Exception JpaSystemException")
    void insertUserJpaSystemException(){
        Exception exception = assertThrows(JpaSystemException.class,()->{
            UserEntity user = UserEntity.builder().build();
            userRepo.save(user);
            userRepo.flush();
        });
        log.error(exception.getClass().getName());
        exception.printStackTrace();
        assertThat(exception.getMessage(), containsString("must be manually assigned before calling 'persist()'"));
    }
    @Test
    @DisplayName("Insert User Exception TransactionSystemException")
    void insertUserTransactionSystemException(){
        Exception exception = assertThrows(TransactionSystemException.class,()->{
            UserEntity user = UserEntity.builder().email("").build();
            userRepo.save(user);
            userRepo.flush();
        });
        log.error(exception.getClass().getName());
        exception.printStackTrace();
        assertThat(exception.getMessage(), containsString("Could not commit JPA transaction"));
    }
    @Test
    @DisplayName("Insert User Fill Email")
    @Transactional
    void insertUser(){
        UserEntity user = UserEntity.builder().email("asd@asd.com").build();
        userRepo.save(user);
    }


}
728x90
728x90

728x90
728x90

요구사항? 요청사항?


진행중인 프로젝트에 투입되거나 시작되는 프로젝트에 투입되었을 때 아무래도 가장 먼저 하는게 분석이지 않을까 한다.
코드 분석이든 업무 분석이든
기능을 만들거나 테이블을 만들때 요구사항정의서를 참고하게 되는 경우가 대부분이다.
이전에 진행했던 프로젝트들의 요구사항정의서를 만들어 본적이 없이 그냥 보기만 했다.
그 요구사항 정의서들은 각 프로젝트마다 거의 제각각으로 보이기도 했다.

요구사항 또는 요청사항을 만들어 보는 연습도 해볼겸 작성해보면 어떨까 싶었다.

완벽하진 않아도 일단 해보는 것이 좋을 듯 싶다.

소프트웨어 방법론은 여러가지이다.
폭포수라던가 애자일이라던가
어쨌든 두 방법론 모두 요구사항을 어떻게 정의해 나가는지가 중요하다고 생각이 들었다.

대부분의 프로젝트는 폭포수 방법론을 따르는 경우가 많았고 요구사항을 모두 정의한 뒤에 프로젝트 개발에 들어가는 경우가 많았다.
하지만, 모든 프로젝트가 그렇듯 개발기간 중에 요구사항은 시시때떄로 변경되었다.
어떻게 보면 매번 요구사항이 변경되는 것은 고질적인 문제가 아닐까 싶기도 하다.

애자일 방법론으로 프로젝트를 진행해 본적은 없다.
그렇기 때문에 생소하기도 하고 개념적으로 이해한다고 하더라고 경험이 없는 것은 아쉬운 마음에 아는 한도 내에서
애자일 방법론(그냥 내 마음대로)에 따라 해보려고 한다.

https://www.atlassian.com/ko/agile/product-management/requirements

위 글을 참고해 보았다.

총 4단계로 나눠 져있는데

여기서는 목표를 적하고 이 목표에 대한 스토리를 작성해 본다.

1. 목표


요구사항의 목표는 사용자가 회원가입을 하고 로그인을 완료하는 것이다.

  1. 회원가입
  2. 로그인 성공

이라는 2개의 목표를 가지고 있다.

2. 스토리


  1. 사용자는 로그인을 하려고 한다.
  2. 로그인을 하기 위해서는 이메일과 비밀번호가 필요한다.
  3. 회원가입이 안되었을 경우 회원 가입을 진행한다.
  4. 회원가입이 되어있을 경우 로그인을 진행한다.
  5. 로그인이 성공하면 AccessToken과 RefreshToken / 사용자 정보를 전달 받는다.
  6. 로그인이 실패하면 실패사유를 전달 받는다.

사용자가 로그인에 성고하기위한 스토리를 작성해 보았다.

위 스토리를 토대로 세부적으로 조금 더 작성해 보자.

  1. 사용자는 로그인을 하려고 한다.
  • 사용자가 로그인 화면에 접근할 수 있는 URL이 필요하다.
  1. 로그인을 하기 위해서는 이메일과 비밀번호가 필요한다.
  • 로그인 화면에는 이메일과 비밀번호입력 받는 화면
  • 로그인 실행 버튼
  • 비밀번호 마스킹
  1. 회원가입이 안되었을 경우 회원 가입을 진행한다.
  • 회원가입 화면으로 이동하는 버튼
  • 회원가입시 필수 사항과 선택 사항
  1. 회원가입이 되어 있을 경우 로그인을 진행한다.
  2. 로그인이 성공하면 AccessToken과 RefreshToken / 사용자 정보를 전달 받는다.
  • 로그인 인증 방식은 JWT
  • 토큰 만료 시간
  • 반환할 사용자 정보 항목
  1. 로그인 실패하면 실패사유를 전달 받는다.
  • 실패시 메시지
  • 메시지 표시 화면

등을 좀더 세부적으로 작성해 보았다.

회원가입 화면으로 넘어 갔을 때 는 어떨까

  1. 회원 가입에 필요한 항목을 작성한다.
  • 필수 : 이메일 / 비밀번호 / 비밀번호 확인 / 이름
  1. 회원 가입 버튼 클릭
  • 필수 항목 체크
  • 유효성 검사
  1. 회원 가입 취소 시 이전 화면 으로 이동
  • 취소 버튼
  • 이전에 접속한 URL
  1. 회원 가입 성공시 로그인 화면으로 이동
  2. 회원가입 실패시 실패 사유 알림
  • 실패시 메시지
  • 메시지 표시 화면

등을 작성해 볼 수 있을 거 같다.

분류해보기


위에서 작성한 스토리를 바탕으로 클라이언트 / 서버 / 데이터베이스 3개의 관점으로 분류해보면 어떨까 싶다.

데이터 베이스


사용자는 이메일과 비밀번호를 로그인 시에 입력하고 또 회원가입 시 필수 정보로 입력하고 있다.그리고 이름을 필수 항목으로 받고 있다.
데이터 베이스에서는 이 항목들이 들어가야한다.

 

728x90
728x90

흐름도 / 흐름도 / 흐름도 그리기는 너무 어려워 !

그래도 해보자!

 

DFD (Data Flow Diagram)

https://en.wikipedia.org/wiki/Data-flow_diagram

 

Data-flow diagram - Wikipedia

From Wikipedia, the free encyclopedia Graphical representation of the "flow" of data through an information system Data flow diagram with data storage, data flows, function and interface A data-flow diagram is a way of representing a flow of data through a

en.wikipedia.org

 

사실 순서도나 흐름도 는 간혹 그려보기는 했지만, 전체적인 프로젝트에 대해 그려보지는 못했다 . 

API 시퀀스 다이어그램을 만들어 보기는 했지만

https://twentytwentyone.tistory.com/195

 

[관리자 페이지] Admin Page - 로그인 프로세스 생각해보기 #1

Admin Page - 로그인 프로세스 생각해보기 User가 Admin Page에 접근했을 경우 User의 Token 이 존재 하는지 확인 존재 한다면 Server에서 Token 발송 검증 요청 User 정보 return Token 이 없다면 Sign In Page로 이동

twentytwentyone.tistory.com

https://twentytwentyone.tistory.com/196

 

[관리자 페이지] Admin Page - 로그인 프로세스 생각해보기 #2

[관리자 페이지] Admin Page - 로그인 프로세스 생각해보기 #2 User는 먼저 로그인 화면으로 진입합니다. 로그인 할 수 있는 아이디나 패스워드가 없는 경우 회원가입을 진행하고 회원가입이 정상적

twentytwentyone.tistory.com

 

Draw.io를 사용해 계속해서 그려보는 연습을 해려고한다.

 

Draw.io는 이전에 웹에서만 사용했었는데 데스크탑 앱을 받을 수 있어서(이전에도 있었나?) 설치 후 사용했다.

 

처음 그려본 로그인 DFD 

 

 

 

뭔가 초라한 느낌 ㅎㅎㅎ

맞게 그린지도 모르겠지만 어쨌든 그려 봤다.

 

728x90
728x90

필요한 유틸리티 기능은 무엇이 있을까?


프로젝트를 진행하다보면 기존의 코드를 사용하던 처음 부터 구축하여 진행을 하던간에 공통 유틸리티 성의 코드를 가져다 쓰거나 만들어서 쓰는 일들이 많은 것 같다.

대부분의 요구사항에는 파일이나 엑셀, 암호화 등의 기능을 요구하는 곳이 많기도 하고 접근에 관한 이력을 DB에 저장해야하는 경우도 많았다.

  • 파일 유틸
  • 암호화 유틸
  • 엑셀 유틸
  • request 유틸
  • session 유틸

등이 기본적으로 필요했고, 많이 쓰였다.

더 많은 프로젝트를 접해 보면 더 좋겠지만, 위와 관련된 코드들을 구현해 보면 좋겠다는 생각이 들었다.

유틸리티 class


보통 이전의 유틸리티 class들을 static으로 불러와 많이 사용하였다. 요즘은 new 또는 @Component로 DI 를 통해 사용한다고 하는데 그 기준이 어떻게 되는지는 모르겠다.

아마도 객체 상태에 대한 이해와 java에서 사용되는 static에 대한 이해, 클래스 메소드가 어디서 무엇을 위해 사용되는지 이해하면 좋을 듯 싶었다.

static은 클래스 단위로 관리되어 메모리 사용량을 줄이고, 객체 생성 오버헤드 없이 접근할 수 있다. 라는 설명을 본적이 있는데, static 멤버 변수를 전역으로 공유 되기 때문에 특정 시점에서의 생성된 객체에 특정 멤버 변수의 값을 변화 시켜야 하는 작업이라면 static 보다는 instance의 유틸을 만들어 보는것이 좋지 않을까 싶다.

728x90

+ Recent posts