[배포 후]nginx 설정 후 쿠키가 전달되지 않는 경우

개발공부·2023년 2월 22일
0

* 상황

▶ 쿠키가 전달되지 않음(그로 인해 로그인이 되지 않음)

* 무엇이 문제라고 생각했나?

▶ 도메인과 도메인 사이간 쿠키를 연결하는 과정에서 nginx가 들어간 부분을 잊은 채, 해결책을 찾으려고 함
express-session을 이용했기에 관련 github 참고

Note be careful when setting this to true, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.
-> HTTPS일 때는 secure: true, 로컬일 때는 secure: false

Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set. If you have your node.js behind a proxy and are using secure: true, you need to set "trust proxy" in express:
-> HTTP를 통해 사이트에 액세스하는 경우 쿠키는 설정되지 않음, proxy 뒤에 node.js가 있고 secure:true를 사용하는 경우 다음과 같이 "trust proxy"를 설정해야 합니다

var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

[쿠키 속성 정리]

  • cookie

세션 ID 쿠키에 대한 설정 개체
기본값은 {path: '/', httpOnly: true, secure: false, maxAge: null}

  • cookie.domain

도메인 집합-쿠키 특성의 값을 지정. 기본적으로 도메인은 설정되지 않으며 대부분의 클라이언트는 쿠키가 현재 도메인에만 적용되는 것으로 간주

  • cookie.httpOnly

HttpOnly Set-Cookie 특성에 대한 true, false 지정
true인 경우 HttpOnly 특성이 설정되고, false는 설정되지 않음
httpOnly:true인 경우 호환되는 클라이언트는 클라이언트 측 JavaScript에서 document.cookie의 쿠키를 볼 수 없음

  • cookie.sameSite

sameSite:true 동일한 사이트 시행에 대해 SameSite 특성을 Strict로 설정

sameSite:false는 SameSite 특성을 설정하지 않음

sameSite:'lax'는 동일한 사이트를 느슨하게 적용하기 위함

sameSite:'none'은 명시적인 교차 사이트 쿠키에 대해 SameSite 특성을 없음으로 설정

sameSite:'strict'는 엄격하게 동일한 사이트를 시행하기 위함

1. 서버쪽 session과 쿠키 설정

▶ 설정을 했음에도 쿠키가 전달되지 않음
▶ 여러 검색을 통해 nginx를 확인해야 함을 알게 됨

if (process.env.NODE_ENV === "production") {
  app.use(morgan("combined"));
  app.use(hpp());
  app.use(helmet());
  app.set("trust proxy", 1); //배포 시 추가
  app.use(
    cors({
      origin: "https://engword.shop", //local "http://localhost:3000"
      credentials: true,
    })
  );
} else {
  app.use(morgan("dev"));
  app.use(
    cors({
      origin: true,
      credentials: true,
    })
  );
}

passportConfig();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.COOKIE_SECRET));

app.use(
  session({
    saveUninitialized: false,
    resave: false,
    secret: process.env.COOKIE_SECRET,
    proxy: true, //배포 시 추가
    cookie: {
      httpOnly: true,
      secure: process.env.NODE_ENV === "production" ? true : false, //https 적용 시 true
      sameSite: process.env.NODE_ENV === "production" ? "none" : false,
     domain: process.env.NODE_ENV === "production" && ".engword.shop",
    },
  })
);
app.use(passport.initialize());
app.use(passport.session());

2. nginx 설정

2-1. nginx 설정하기는 다른 블로그 글에 정리함

* 해당 부분은 backendnginx임(front쪽은 기본 코드라고 작성된 부분으로도 충분함)

sudo vim /etc/nginx/nginx.conf

* 기존 코드

https://api.engword.shop 접속 시 nginx http://127.0.0.0:3005으로 대리함

server {
	server_name api.engword.shop;
    location / {
    	proxy_set_header HOST $host;
        proxy_pass http://127.0.0.0:3005; 
        proxy_redirect off;
    }
    //아래는 certbot 내용
}

* 추가한 내용

▶ 참고 : 제로초 블로그

server {
	server_name api.engword.shop;
    location / {
    	proxy_set_header HOST $host;
        //추가
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
       	proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.0:3005; 
        proxy_redirect off;
    }
    //아래는 certbot 내용
}

* 추가 후 nginx 다시 시작

sudo systemctl restart nginx

3. 결과(정상적으로 동작함)

▶ 노랑색 표시가 Set-cookie

[nginx 속성 정리]

제로초 nginx와 let's encrypt로 SSL 적용하기(+자동 갱신)
nginx 참고 블로그 글
proxy 참고 블로그 글2

* nginx 없이 localhost로만 웹서버 운영 시 단점

▶ 사용자가 갑자기 많아지거나 웹서버가 그대로 노출 시 보안 위험성 증가

* nginx 사용 시 로드 밸런싱으로 부하를 줄이고 분산 처리가 가능하며 웹 서버의 SSL 인증도 적용 가능

▶ 로드 밸런싱(출처: aws) : 애플리케이션을 지원하는 리소스 풀 전체에 네트워크 트래픽을 균등하게 배포하는 방법
-> 애플리케이션 서버와 방문자 또는 클라이언트 간의 인터넷 트래픽을 지시하고 제어
-> 애플리케이션의 가용성, 확장성, 보안 및 성능 향상

▶ SSL 인증([출처: 생활코딩](https://opentutorials.org/course/228/4894)) : SSL 인증서는 클라이언트와 서버간의 통신을 제3자가 보증해주는 전자화된 문서

  1. 통신 내용이 공격자에게 노출되는 것을 막을 수 있음
  2. 클라이언트가 접속하려는 서버가 신뢰 할 수 있는 서버인지를 판단할 수 있음
  3. 통신 내용의 악의적인 변경을 방지할 수 있음

-> HTTPS와 SSL을 같은 의미로 이해하도 하는데 맞기도 하고 틀리기도 함(인터넷과 웹을 같은 의미로 이해하는 것과 마찬가지)
-> 웹이 인터넷 위에 돌아가는 서비스 중 하나처럼, HTTPS도 SSL 프로토콜 위에서 돌아가는 프로토콜(컴퓨터 내부에서, 또는 컴퓨터 사이에서 데이터의 교환 방식을 정의하는 규칙 체계)

  • Nginx는 요청을 프록시(정보를 대신 전달해주는 개체)할 때 클라이언트의 프록시 요청인 호스트 및 연결에서 두 개의 헤더 필드를 자동으로 정의하고 빈 헤더를 제거 호스트가 $proxy_host 변수로 설정되고 연결이 닫히도록 설정됩니다.

* proxy_set_header 부분은 Header들을 넘겨주는 코드

참고 블로그 글

Host $host : 다음 우선 순위의 $host 변수에는 요청 라인의 호스트 이름 또는 호스트 요청 헤더 필드의 호스트 이름 또는 요청과 일치하는 서버 이름이 포함됨
X-Forwarded-Proto : https를 할 때 필요
UpgradeConnection : 웹소켓을 할 때 필요
X-Real-IPX-Forwarded-For : IP를 알아내고 싶을 때 있으면 좋음
X-Forwarded-Proto $scheme : HTTPS 서버 블록 내에서 사용할 경우 프록시 서버의 각 HTTP 응답이 HTTPS로 다시 작성

		proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
       	proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.0:3005; 
        proxy_redirect off;
    
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글