728x90

@Transactional을 붙이자

728x90
728x90

mappedBy와 @JoinColumn을 같이 사용해서 발생

 

연관관계 주인이 어느쪽인지 확인하자

728x90
728x90

md5 암호화 중 byte[]를 String 으로 만들기 위해 사용한 패키지

// https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api
implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '4.0.2'

 

의존성 추가

 

DatatypeConverter.printHexBinary(byteArray);
728x90

'study > spring-boot' 카테고리의 다른 글

[Spring boot] mariadb + jpa 대문자로 만들기  (0) 2024.05.17
[spring boot] thymeleaf th:href / th:src  (0) 2022.12.26
[spring boot] thymeleaf layout  (0) 2022.12.26
@EnableTransactionManagement  (0) 2022.10.11
vscode refresh gradle  (0) 2022.10.11
728x90

AWS 액세스 방식은 3가지

1. 콘솔 (이메일 + 비밀번호 + @MFA)

2. CLI(Access Key)

3. SDK (Access Key)

관리 콘솔을 통해 엑세스 키 생성

유저는 자신의 엑세스 키를 관리

엑세스키와 비밀엑세스키

CLI (Command Line Interface)

모든 명령어가 aws로 실행

자동화 가능

CLI github.com/aws/aws-cli 참고 가능

SDK (Software Development Kit)

특정 언어 APIs

애플리케이션에 임베드

여러 언어 지원

IoT 지원

AWS CLI 설치

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

[최신 버전의 AWS CLI설치 또는 업데이트 - AWS Command Line Interface

이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

docs.aws.amazon.com](https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html)

엑세스 키 만들기

콘솔 -> IAM -> USER -> 유저 클릭 -> security credentials -> Access Key

CLI 선택 확인 > 엑세스 키 생성

AWS CLI 구성

서울 리전 : ap-northeast-2

aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: ap-northeast-2
Default output format [None]:

AWS user lists

aws iam list-users

{
    "Users": [
        {
            "Path": "/",
            "UserName": "TILAWS",
            "UserId": "",
            "Arn": "arn:aws:iam::533267005019:user/TILAWS",
            "CreateDate": "2024-05-14T06:29:53+00:00",
            "PasswordLastUsed": "2024-05-14T06:41:06+00:00"
        }
    ]
}
  • UserName : 유저 이름
  • UserId : 유저 Access ID
  • Arn : Amazon 리소스 이름
  • CreateDate : 생성일자
  • PasswordLastUsed : 마지막 비밀번호 사용 시기

CLOUD SHELL 사용가능 리전

https://docs.aws.amazon.com/cloudshell/latest/userguide/supported-aws-regions.html

 

Supported AWS Regions for AWS CloudShell - AWS CloudShell

Supported AWS Regions for AWS CloudShell This section covers the list of supported AWS Regions and Opt-in Regions for AWS CloudShell. For a list of AWS service endpoints and quotas for CloudShell, see the AWS CloudShell page in the Amazon Web Services Gene

docs.aws.amazon.com

 

728x90

'study > TIL' 카테고리의 다른 글

[TIL] 2024-05-21 AWS  (0) 2024.05.21
[TIL] 2024-05-17 AWS  (0) 2024.05.17
[TIL] 2024-05-16 AWS  (0) 2024.05.16
[TIL] 2024-05-14 AWS  (0) 2024.05.14
[TIL] 2024-05-13 AWS  (0) 2024.05.13
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
spring:
    jpa:
        hibernate:
              naming:
                physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
728x90

'study > spring-boot' 카테고리의 다른 글

[SPRING BOOT] DatatypeConverter  (0) 2024.05.21
[spring boot] thymeleaf th:href / th:src  (0) 2022.12.26
[spring boot] thymeleaf layout  (0) 2022.12.26
@EnableTransactionManagement  (0) 2022.10.11
vscode refresh gradle  (0) 2022.10.11
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

AWS MFA Google Authenticator

 

 

비밀번호 정책 설정

계정 설정

 

암호 정책  > 편집 클릭

 

 

 

기본 정책

 

 

사용자 지정에서 선택가능

 

 

MFA 설정

 

 

프로필 클릭  > 보안 자격 증명

 

MFA 할당

 

이름 입력 

 

Authenticator app 선택 > 다음

 

 

Authenticator app 에서 QR 코드 또는 보안키 입력 후 첫번째 코드 입력 기다렸다가 두번째 코드

 

추가 성공 시 멀티 팩터 인증에 나옴

728x90

'study > TIL' 카테고리의 다른 글

[TIL] 2024-05-21 AWS  (0) 2024.05.21
[TIL] 2024-05-20 AWS  (0) 2024.05.20
[TIL] 2024-05-16 AWS  (0) 2024.05.16
[TIL] 2024-05-14 AWS  (0) 2024.05.14
[TIL] 2024-05-13 AWS  (0) 2024.05.13
728x90

AWS

IAM

비밀번호 정책

AWS 에서는 다양한 선택을 통해 비밀번호정책을 생성 가능함

최소 길이

허용 문자 / 숫자 / 특수기호

비밀번호 허용 또는 금지 가능

일정시간이 지나면 만료 안내를 통해 새롭게 비밀번호 설정하도록 할 수 있음

 

MFA - Multi Factor Authentication

비밀번호와 보호장치를 함꼐 사용하는 것

가상 MFA 장치

Google Authenticator ( 폰만)

Authy(여러장치)

 

Yubico 사 Yubikey 범용 키 장치

하드웨어 Key Fob 키팝 

 

 

728x90

'study > TIL' 카테고리의 다른 글

[TIL] 2024-05-20 AWS  (0) 2024.05.20
[TIL] 2024-05-17 AWS  (0) 2024.05.17
[TIL] 2024-05-14 AWS  (0) 2024.05.14
[TIL] 2024-05-13 AWS  (0) 2024.05.13
[TIL] 2024-05-10 AWS  (0) 2024.05.10
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

+ Recent posts