Deploy environment EC2, RDS
✅ EC2
스프링을 올릴 수 있는 서버
- 로컬 컴퓨터가 아니라 원격 컴퓨터를 배정 받아서 사용
- 원격 컴퓨터 OS는 ubuntu를 사용
- 배포 전 원격 컴퓨터에
java JRE
,git
,netstat
설치할 예정
☑️ AWS EC2 설정하기
- region: 한 지역으로 설정하고 고정
- 인스턴스 유형: 프리 티어
- OS는 ubuntu
- 키 페어: make new key pair
💡 이름 지을 때 띄어쓰기 하지 말 것(나중에 terminal에서 띄어쓰기 인식 못함) - 네트워크: vpc-어쩌고저쩌고
💡 이후 RDS할 때vpc-0c6562bc157853529
가 동일해야 하므로 꼭 기억해두기 - 스토리지 구성: 30GB
☑️ 보안그룹 추가
EC2 ▶️ 네트워크 및 보안 ▶️ 보안 그룹 보안그룹을 추가해서 방화벽을 해제하기
- 인바운드 규칙에 모든 TCP - Anywhere IPv4, IPv6 총 2개 추가
- 이렇게 방화벽을 해제해야 local에서도 서버 접속 가능
💡 이 때 VPC 주소 EC2와 일치하도록 주의
➡️ EC2에 보안그룹 추가
✔️ 결과: 인바운드 규칙 추가
🟢 Terminal 1: keypair pem + SSH로 연결
원격 컴퓨터와 로컬 컴퓨터를 연결한다.
- keypair을 생성하면 Downloads에 저장된다.
- Downloads에 폴더 하나 만들어서
- 거기에다가 keypair을 복사한다.
- keypair이 있는 장소로 들어가서
sudo chmod
로 키에 권한을 설정하고 ssh
로 연결한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- Desktop으로 들어가
~/Desktop
-- Downloads로 들어가
~/Downloads
-- drugstore-key라는 폴더 만들어
mkdir drugstore-key
-- drugstore-key 폴더 안으로 들어가
cd drugstore-key
-- drugstore-key 폴더에 Downloads안에 있는 DrugStoreKeyPair.pem . 라는 키페어 복사해
cp ~/Downloads/DrugStoreKeyPair.pem .
-- keypair
-- sudo chmod 400 pem 키 이름: 들어올 수 있는 권한을 주기
sudo chmod 400 DrugStoreKeyPair.pem
ssh -i "DrugStoreKeyPair.pem" ubuntu@ec2-54-180-126-207.ap-northeast-2.compute.amazonaws.com
✔️ 결과: ~/Downloads
에 폴더 있고, 폴더 안에 우리의 pem
키 있어야 한다.
✔️ 결과: ubuntu@ ip주소
1
2
-- ip- 내 ip번호
ubuntu@ip-172-31-10-19:~$ 이제 여기에 명령어 쓸 것
🟢 Terminal 1: 원격 컴퓨터 ubuntu에 폴더 만들어 java, git, netstat install
이제 EC2에서 배정받은, 내가 선택한 지역(서울)에 있는 원격 컴퓨터를 배정받아 연결한 상태임 이 컴퓨터에는 아무것도 설치되어 있지 않음 따라서 java, git, netstat 설치 필요
먼저 임시 서버에 들어와 ubuntu@ip-172-31-10-19:~$
된 상태인지 확인하고 시작!
1
2
3
4
pwd
-- /home/ubuntu
mkdir spring
cd spring
✔️ 결과: ubuntu@ip-172-31-10-19:~/spring$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 먼저 업데이트 하고
sudo apt update
-- 자바 설치
java -version
-- java 버전 여러개 뜨면 내가 설치하고 싶은 버전의 java설치
sudo apt install openjdk-17-jre-headless
-- 깃 이미 설치되어 있음
git --version
-- net-tools 설치
sudo apt install net-tools
netstat -h
🟢 Terminal 1: 서버 열기, 네트워크 확인하기
sudo netstat
: 현재 서버의 네트워크 설정이 어떻게 되어있는지 확인하기
l
: listen
t
: tcp/udp 중에 tcp
p
: process
n
: 실제 포트 번호
1
sudo netstat -ltpn
✔️ 결과
1
2
3
4
5
6
ubuntu@ip-172-31-10-19:~/spring$ sudo netstat -ltpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.54:53 0.0.0.0:* LISTEN 321/systemd-resolve
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 321/systemd-resolve
tcp6 0 0 :::22 :::* LISTEN 1/init
🟢 Terminal 1: 8080 연결
8080 port로 임시 서버를 연다.
1
2
nc -lkv 8080
-- Listening on 0.0.0.0 8080
🔵 Terminal 2: keyPair있는 곳에서 임시서버와 연결
keyPair있는 폴더로 들어가기
ssh연결에서 보이는 링크로 들어가기
1
2
3
4
~/Desktop
~/Downloads
cd drugstore-key
ssh -i "DrugStoreKeyPair.pem" ubuntu@ec2-54-180-126-207.ap-northeast-2.compute.amazonaws.com
임시 서버에 들어와 ubuntu@ip-172-31-10-19:~$
된 상태에서 시작
1
2
sudo netstat -ltpn
nc -v localhost 8080
✔️ 결과: 8080 추가된 것 보이죠?!
1
2
3
4
5
6
7
ubuntu@ip-172-31-10-19:~$ sudo netstat -ltpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.54:53 0.0.0.0:* LISTEN 321/systemd-resolve
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 321/systemd-resolve
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2115/nc //⭐️ 새로 생긴걸 확인할 수 있다.
tcp6 0 0 :::22 :::* LISTEN 1/init
✔️ 결과
1
2
ubuntu@ip-172-31-10-19:~$ nc -v localhost 8080
-- Connection to localhost (127.0.0.1) 8080 port [tcp/http-alt] succeeded!
🟣 Terminal 3: 로컬에서 서버와 연결
로컬에서 서버와 연결을 위해서는 방화벽을 풀어야 한다.
1
2
3
4
-- 로컬에서 서버 연결
-- nc -v 8080
nc -v ec2-54-180-126-207.ap-northeast-2.compute.amazonaws.com 8080
✅ RDS
- 템플릿: 프리 티어
- 자격 증명 설정: 마스터 사용자 이름(db이름) root
- password
- 연결: EC2컴퓨팅 리소스에 연결 안 함 💡 VPC 주소가 EC2와 동일해야 함 (꼭 설정할 것, 데이터베이스 생성 이후에는 VPC변경 불가)
- 퍼블릭 액세스: 예
☑️ 파라미터 그룹
RDS ▶️ 파라미터 그룹
- time_zone 값: Asia/Seoul
- character 들어간 필드 6개 값: utf8mb4
- collation 들어간 필드 2개 값: utf8mb4_general_ci
➡️ RDS에 DB 파라미터 그룹 추가
✔️ 파라미터 그룹 생성
✔️ time_zone 값: 내 region
✔️ character 들어간 필드 6개 값: utf8mb4
✔️ collation 들어간 필드 2개 값: utf8mb4_general_ci
✔️ RDS에 파라미터 그룹 추가
☑️ 보안그룹 추가(EC2에 있음)
- 인바운드 규칙에 모든 MYSQL/Aurora Anywhere IPv4, IPv6 총 2개 추가
💡 이 때 VPC 주소 RDS와 일치하도록 주의
➡️ RDS에 보안 그룹 추가
✔️ RDS에 보안 그룹 추가
✅ MySQL workbench
- Hostname: RDS의 엔드포인트
예를 들어,drugstoreDB.cn000owqib3s.ap-northeast-2.rds.amazonaws.com
- Username: RDS에서 설정한 마스터 사용자 이름
- Password: RDS에서 설정한 비밀번호
➡️ TestConnection, connect anyway
✅ RDS에 EC2 연결
RDS ▶️ 연결된 컴퓨팅 리소스 ▶️ EC2 연결 설정
✔️ 결과: EC2에서도 RDS 연결된 것 확인
EC2 아웃바운드 규칙을 보면 RDS 연결되어 있는 것을 확인할 수 있다.
🟢 Terminal 1: mariaDB설정
ubuntu@ip-172-31-10-19:~/spring$
이렇게 되어 명령어 입력 준비된 상태에서 시작
mariaDB 설치
1
2
3
4
5
6
7
8
9
10
11
12
13
sudo apt install wget
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
echo "f5ba8677ad888cf1562df647d3ee843c8c1529ed63a896bede79d01b2ecc3c1d mariadb_repo_setup" \
| sha256sum -c -
chmod +x mariadb_repo_setup
sudo ./mariadb_repo_setup \
--mariadb-server-version="mariadb-10.11"
sudo apt update
mariaDB client 설치
1
sudo apt install mariadb-client
mysql 잘 있나 확인
1
mysql --version
mysql 들어가기
1
2
3
-- mysql -h RDS엔드포인트 -u DBusername -p
mysql -h drugstoredb.cn000owqib3s.ap-northeast-2.rds.amazonaws.com -u root -p
show databases;
✔️ 결과
1
2
3
4
5
6
7
8
9
10
11
12
MariaDB [(none)]> show databases;
+---------------------------+
| Database |
+---------------------------+
| drug_store_db |
| information_schema |
| innodb |
| mysql |
| performance_schema |
| sys |
+---------------------------+
6 rows in set (0.001 sec)
✅ yaml files
✔️ application.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server: port:8080
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# autoconfigure:
# exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
username: ${DATABASE_USERNAME}
password: ${DATABASE_PASSWORD}
driver-class-name: org.mariadb.jdbc.Driver
url: { { URL } }
jpa:
show-sql: true
jwtpassword:
source: ${JWT_SECRET_KEY}
logging:
level: debug
✔️ application-prod.yaml
1
2
3
4
5
6
7
8
9
10
11
spring:
config:
activate:
on-profile: prod
logging:
config: classpath:logback-spring-prod.xml
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: { { URL } }
✔️ application-dev.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
config:
activate:
on-profile: dev
server:
port: 8080
logging:
config: classpath:logback-spring-local.xml
level:
org:
hibernate:
SQL: DEBUG
✔️ application-local.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
config:
activate:
on-profile: local
server:
port: 8080
logging:
config: classpath:logback-spring-local.xml
level:
org:
hibernate:
SQL: DEBUG
✅ build.gradle
build.gradle
에 tasks.named('bootJar')
추가해주기
bootJar
을 실행하면 이 클라스를 실행하라는 것을 알려주는 코드
Application
이 있는 장소, 즉 Copy Reference
1
2
3
4
5
6
7
tasks.named('test') {
useJUnitPlatform()
}
tasks.named('bootJar'){
mainClass =
mainClass = 'com.github.drugstorebe.DrugStoreBeApplication'
}
✅ xml log files
✔️ logback-spring-prod.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATH" value="logs" />
<!-- 콘솔 로그 출력 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/server.log</file>
<append>true</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<!-- 루트 로거 설정 -->
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
✔️ logback-spring-dev.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATH" value="logs" />
<!-- 콘솔 로그 출력 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/server.log</file>
<append>true</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<!-- 루트 로거 설정 -->
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
✔️ logback-spring-local.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 콘솔 로그 출력 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<!-- 루트 로거 설정 -->
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
✅ prod로 실행 확인
✔️ 먼저 실행파일을 prod로 바꾸고
✔️ postMan 돌려보고 잘 작동하는지 확인
✔️ logs 잘 만들어지는지 확인
✔️ libs 아래에 bootJar 파일 잘 만들어지는지 확인
모두 잘 되는거 확인 하고 마지막으로 배포 전 PUSH
✅ ubuntu에 환경변수 저장하기
일단 서버로 들어가기 . 들어가서 시작
1
2
3
4
~/Desktop
~/Downloads
cd drugstore-key
ssh -i "DrugStoreKeyPair.pem" ubuntu@ec2-15-164-219-191.ap-northeast-2.compute.amazonaws.com
환경변수 설정 위해 들어감
spring까지 들어감
1
vim ~/.bashrc
안에서 편집 시작
s누르면 편집 가능
💡 =
사이에 띄어쓰기 하지 않기 주의!
💡 다 편집 후 ESC 누르면 편집 모드에서 read only 모드로 바뀜
그제서야 :wq
눌러서 저장하고 quit
1
2
3
4
#add environment variables
export DATABASE_PASSWORD=비밀번호
export DATABASE_USERNAME=root
export JWT_SECRET_KEY=시크릿키
✔️ vim에서 나왔으면 확인
1
2
3
4
5
6
-- 저장
source ~/.bashrc
-- 하나씩 불러와서 잘 저장되었는지 확인할 것
echo $JWT_SECRET_KEY
echo $DATABASE_USERNAME
echo $DATABASE_PASSWORD
✅ git clone, deploy
ubuntu > spring folder > github project clone
1
2
-- git clone -b 복사할브랜치이름 --single-branch 깃허브 링크
git clone -b deploy --single-branch https://github.com/DrugStoreWeb/DrugStore-BE.git
✔️ 결과
ubuntu > spring안에 깃허브 프로젝트가 만들어진다.
ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
✅ build file만들기
ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
하고 ls
해보면 build파일이 없음.
build파일 만들어야 한다.
1
2
-- build file 만드는 명령어
./gradlew bootJar
그럼 이제 ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
하고 ls
해보면 build파일이 만들어져 있는걸 확인할 수 있다.
이제 build파일 안에 있는 libs파일에 들어가면 SNAPSHOT.jar 파일이 생긴걸 확인할 수 있다.
이렇게 생겼음: DrugStore-BE-0.0.1-SNAPSHOT.jar
1
ls ./build/libs
✔️ 결과
✅ deploy, swagger
⭐️ 게속 ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
에서 이어서 진행 이제 SNAPSHOT.jar 파일을 배포하면, 어떤 컴퓨터에서도 웹페이지 접속 가능
💡 띄어쓰기 주의하기!
- Jar띄고
-jar ./
💡./build/libs/DrugStore-BE-0.0.1-SNAPSHOT.jar
주의
1
java -jar ./build/libs/drug_store_be-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
✔️ 결과
http://EC2퍼블릭 IPv4 DNS 여기에 쓰기
:8080/swagger-ui/index.html
예를 들어, 아래 주소를 넣으면
http://ec2-3-249-108-216.eu-west-1.compute.amazonaws.com:8080/swagger-ui/index.html
이렇게 하면 우리가 만든 백엔드 단이 swagger에 보이게 된다.
✔️ 결과
마찬가지로 포스트맨도 가능하다.
localhost를 EC2퍼블릭 IPv4 DNS
로 바꾸기
🔴 Trouble Shooting
java -jar ./build/libs/drug_store_be-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
을 하고 application start가 뜨기를 기다렸다.
하지만 계속계속 기다리는데 WARN에 멈추더니 터미널이 꿈쩍도 안했다.
심지어 run을 멈추는 방법도 모르겠어서 터미널을 꺼버렸다.
그리고 다시 터미널을 열어 처음부터 시작했다.
그런데 이번에는 ` ssh -i “DrugStoreKeyPair.pem” ubuntu@ec2-54-180-126-207.ap-northeast-2.compute.amazonaws.com` 도 들어가지지가 않았다.
내 ubuntuㅠㅠ 뭐가 문제일까??
🟡 원인: 컴퓨터 CPU과부화일 수도 있다고 한다. 또는 EC2의 문제일 수도 있다.
🔵 우선 컴퓨터에서 실행되는 프로세스들을 멈추고, 컴퓨터 전원을 껐다가 켰다. 하지만 이걸로 해결이 되지 않았다.
🔵 그래서 이번에는 EC2를 중지했다가, 다시 시작했다. 물론 이렇게 하면 퍼블릭 도메인이 바뀐다. 바뀐 도메인 주소로 다시 우분투에 접속한다.
ssh -i "DrugStoreKeyPair.pem" ubuntu@ec2-43-200-67-116.ap-northeast-2.compute.amazonaws.com
이렇게 했더니 잘 접속이 되었고, 이어서 java -jar
까지도 잘 실행되었다. 끝!
✅ terminal꺼져도 끝나지 않는 서버, nohup
지금은 terminal을 꺼버리면 서버도 꺼진다.
따라서 백그라운드에서 저쪽 서버에서 영원히 돌도록 만들기.
💡 띄어쓰기 주의하기!
- Jar띄고
-jar ./
- /dev 띄어쓰기 없음
>>/dev/null
💡./DrugStore-BE/build/libs/DrugStore-BE-0.0.1-SNAPSHOT.jar
주의
ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
까지 들어온 상태에서 진행
1
nohup java -jar ./build/libs/drug_store_be-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod >>/dev/null 2>&1 &
또는 ubuntu@ip-172-31-10-19:~/spring$
까지 들어온 상태에서 진행
1
2
nohup java -jar ./build/libs/drug_store_be-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod >>/dev/null 2>&1 &
💡 추가
nohup.out파일을 생성하기 위해서는 다음과 같은 명령어를 실행해야 한다.
1
nohup java -jar ./build/libs/drug_store_be-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod &
✔️ 결과
4자리 숫자가 출력되어야 한다.
그리고 네트워크 상태 확인하면 새로운 tcp 있음
이제 터미널을 꺼도 잘 실행된다.
1
netstat -ltpn
✅ IP고정하기
AWS EC2를 중지했다가 다시 시작하게 되면 EC2퍼블릭 IPv4 DNS
가 바뀐다.
따라서 바뀌지 않는 탄력적 IP를 지정한다.
EC2에 탄력적 IP
- 탄력적 IP 주소 할당
- 만든 탄력적 IP에 주소 연결, 우리가 만든 instance연결
이후 인스턴스에 들어가면탄력적 IP 주소
라는게 생김
이제EC2퍼블릭 IPv4 DNS
대신에탄력적 IP 주소
를 넣는다.
1
2
3
4
5
6
7
-- 이전
ssh -i "DrugStoreKeyPair.pem" ubuntu@ec2-43-200-67-116.ap-northeast-2.compute.amazonaws.com
http://ec2-43-203-126-199.ap-northeast-2.compute.amazonaws.com:8080/auth/sign-up
-- IP고정 이후
ssh -i "DrugStoreKeyPair.pem" ubuntu@43.200.67.116
http://43.200.67.116:8080/auth/login
✔️ 결과
swagger주소 이제 이렇게 생김
1
http://43.200.67.116:8080/swagger-ui/index.html
✅ 진짜 마지막으로 IP주소 백그다운드에서 run
1
2
3
4
~/Desktop
~/Downloads
cd drugstore-key
ssh -i "DrugStoreKeyPair.pem" ubuntu@43.200.67.116
그러면 ubuntu@ip-172-31-10-19:~/$
이후 ubuntu@ip-172-31-10-19:~/spring/$
까지 들어와서
ubuntu@ip-172-31-10-19:~/spring/DrugStore-BE$
까지 들어온 상태에서 진행
1
nohup java -jar ./build/libs/DrugStore-BE-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod >>/dev/null 2>&1 &
💡 개선 포인트
- bash script
여러번 반복되는 bash 명령어는 bash script 만들어 활용하기 - github action CI/CD
여러 툴 사용하여 빌드/배포 자동화 가능
✅ CORS
☑️ kill server
Identify the Process ID (PID) of the Server Process
1
sudo netstat -tulpn | grep :8080
Stop the Server Process
1
sudo kill PID
이제 다시 sudo netstat -tulpn | grep :8080
하면 아무것도 안 뜬다.
☑️ erase git cloned file
현재 ubuntu@ spring 안에 깃허브 클론 폴더 만들어져 있는 상태
1
2
3
ubuntu@ip-172-31-10-19:~/spring$ ls
DrugStore-BE logs mariadb_repo_setup mariadb_repo_setup.1 mariadb_repo_setup.2 nohup.out
-- DrugStore-BE가 깃허브 클론한 것
깃 클론 지우기
1
sudo rm -r DrugStore-BE
☑️ security config에 cors관련 세팅 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import github.com.jbabe.service.exception.CustomAuthenticationEntryPoint;
import github.com.jbabe.service.exception.CustomExceptionDeniedHandler;
import github.com.jbabe.web.filters.JwtFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtTokenConfig jwtTokenConfig;
// private final JwtExceptionFilter jwtExceptionFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.headers(h -> h.frameOptions(f -> f.sameOrigin()))
.csrf((c) -> c.disable())
.httpBasic((h) -> h.disable())
.formLogin(f -> f.disable())
.rememberMe(r -> r.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.cors(c-> c.configurationSource(corsConfig())) //add
.authorizeRequests(a ->
a
.requestMatchers("/test","v1/api/competition/add-competition-info").hasRole("MASTER")
.requestMatchers("/v1/api/sign/logout").authenticated()
.requestMatchers("/resource/static/**", "/v1/api/sign/sign-up", "/v1/api/sign/login",
"/mail/*", "v1/api/competition/competition").permitAll()
)
.exceptionHandling(e -> {
e.authenticationEntryPoint(new CustomAuthenticationEntryPoint());
e.accessDeniedHandler(new CustomExceptionDeniedHandler());
})
.addFilterBefore(new JwtFilter(jwtTokenConfig), UsernamePasswordAuthenticationFilter.class);
// .addFilterBefore(jwtExceptionFilter, JwtFilter.class);
return http.build();
}
//한솔 버전
private CorsConfigurationSource corsConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(List.of("*")); // TODO: 쿠키사용 시 변경
// corsConfiguration.setAllowCredentials(true); // TODO: 쿠키사용 시 변경
corsConfiguration.addExposedHeader("access-token");
corsConfiguration.addExposedHeader("refresh-token");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.setAllowedMethods(List.of("GET","PUT","POST","PATCH","DELETE","OPTIONS"));
corsConfiguration.setMaxAge(1000L*60*60);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return source;
}
//troubleShooting 완료한 버전
private CorsConfigurationSource corsConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(false);
corsConfiguration.setAllowedOrigins(List.of("*"));
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addExposedHeader("Token"); //추가
corsConfiguration.setExposedHeaders(Arrays.asList("Authorization", "Authorization-refresh", "Token"));
corsConfiguration.setAllowedMethods(List.of("GET","PUT","POST","DELETE"));
corsConfiguration.setMaxAge(1000L*60*60);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return source;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
☑️그리고 git commit, push 한다음 또 deploy
➡️ 목차에서 git clone, deploy
로 가서 거기서부터 따라하기