[php/aws] session과 session.gc_maxlifetime에 대해(로그인 세션)

프로그래밍/서버2020. 8. 29. 14:19

운영 중인 앱에서 버그가 발견됐습니다.

서버 쪽 문제로 보이는데 구글 로그인 후.. 로그인 세션이 제대로 유지되지 않는 것 같습니다.

 

저는 세션 파일을 기본 경로에 생성되도록 했습니다.

/opt/bitnami/php/tmp

 

위의 경로에 로그인 관련 세션 파일이 생성됩니다.

 

FileZillia로 서버에 접속해서 세션 파일을 봤습니다. 세션 파일이 하루는 유지될 줄 알았는데 확인 시점으로.. 가장 오래된 것이 4시간 정도 밖에 안되더라구요.

 

뿌띠(Putty)에서 간단하게 명령어로 세션 유지 시간을 알 수 있습니다.

php -r 'echo ini_get("session.gc_maxlifetime"), "\n";'

 

기본값은 1440인데 이는 1440초 즉 24분 뒤에 GC(Garbage Collector)가 삭제하는 파일에 포함이 된다는 의미입니다.

그런데 여기서 중요한 것이 GC는 무거운 동작이라.. 자주 발생하지 않습니다. 그래서 실제로는 바로 24분 뒤에 삭제되지 않습니다.

 

php --ini

뿌띠에서 위의 명령어를 입력하면 php.in의 파일 위치를 알 수 있습니다.

저는 /opt/bitnami/php/etc 경로에 있네요.

 

php.ini에 가면.. 세션 GC와 관련된 몇 가지의 설정 값들이 있습니다.

 

session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440

 

session.gc_probability와 session.gc_divisor는 GC 실행확률을 나타내는데 session.gc_probability/session.gc_divisor 확률로 세션이 초기화될 때 GC도 동작하는 것 같습니다. 그러니까 위의 예에선 1/1000으로 세션이 시작할 때마다 0.1%확률로 GC가 동작하여 생성된지 24분(=1440초)이 넘은 파일은 삭제합니다.

 

가만히 있어서는 세션 파일이 삭제되지 않습니다. 그래서 의도적으로 구글 로그인을 10~20번 정도 반복했습니다. GC가 실행될 확률이 1~2%밖에 안될텐데.. 운이 좋게도 GC가 실행된 것 같습니다.

GC수행 후.. 생성된지 24분이 넘는 세션 파일은 다 삭제가 됐습니다.

 

저는 이 세션 파일이 3일 정도는 유지가 됐으면 하므로.. 

session_gc_maxlifetime의 값을 1440에서 259200(=60*60*24*3)으로 변경했습니다.

 

sudo /opt/bitnami/ctlscript.sh restart apache

변경한 내용이 적용되도록 위의 명령어로 서버를 재시작 해줍니다.

 

이 변경사항으로 인해 기존에 발생하던 문제가 해결됐는지 아닌지 확인하려면 시간을 두고 좀 살펴봐야 할 것 같습니다.

 

*2020년 8월 30일 추가

위의 변경사항으로 인해 서버의 세션 파일을 유지시간이 길어진 것을 확인했습니다. 음.. 그런데 로그인 세션 관련된 문제가 해결되지는 않았네요. 클라이언트 쪽의 문제일 수도 있어 더 확인해보려고 합니다.

 

 

php서버에서 session_start()함수를 실행하면.. client로 response를 보낼 때 자동으로 헤더에 Set-Cookie를 추가하여 client에서 세션 정보를 쿠키에 저장되도록 합니다. 

<?php
 session_start();
?>

 

만약 서버로 전달된 request의 header cookie에 php서버에서 사용하는 세션(session_name)이 있는 경우에는 이 세션을 계속 사용하면 되므로 이 경우는 client로 response를 보낼 때 Set-Cookie를 보내지 않습니다. 왜냐면 이미 그 전에 서버에서 client로 Set-Cookie를 보냈고.. 그래서 client가 그 쿠키값을 서버로 보낸 상황이기 때문에 이미 세션이 설정된 상태니까요.

 

쿠키에 저장되는 세션 정보는 세션 쿠키라고 하여.. 다른 쿠키와는 만료시간의 차이가 있습니다. 일반적인 쿠키가 만료시간이 있어 브라우저를 종료하더라도 그 만료시간까지 살아있는 반면, 션 쿠키는 기본적으로 만료시간이 없고 브라우저가 종료되면 삭제됩니다.(세션 쿠키는 일반적으로 민감한 정보이기 때문)

 

저의 경우.. 안드로이드에서 브라우저(앱)가 종료되더라도 로그인이 더 유지됐으면 합니다.

<?php
session_set_cookie_params(259200,"/");
session_start();
?>

3일 정도는 유지됐으면 하는데 위와 같이 session_set_cookie_params() 함수를 이용하면 만료시간을 설정할 수 있습니다.

(stackoverflow.com/questions/6360093/how-to-set-lifetime-of-session)

 

이렇게 서버의 설정을 바꾸고 안드로이드 앱에서 확인해봤습니다.

 

서버에서 오는 response header를 확인해봤습니다.

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {

    Headers allHeaders = response.headers();
    Iterator<Pair<String, String>> iterator = allHeaders.iterator();
    while(iterator.hasNext()){
        Pair<String, String> pair = iterator.next();
        Log.d(TAG, "onResponse: header: " + pair.getFirst() + " = " + pair.getSecond());
    }

OkHttp의 onResponse()에서 위와 같은 방법으로 response header를 확인할 수 있습니다. 기존의 Set-Cookie에 만료시간이 추가된 것을 확인할 수 있었습니다.

 

실제로 안드로이드 쿠키에 저장된 값은 아래와 같이 확인할 수 있습니다.

List<Cookie> cookies = NetworkManager.getInstance().getClient().cookieJar().loadForRequest(response.request().url());
for(int i=0; i<cookies.size(); i++) {
    Log.d(TAG, "LoginActivity: onResponse: cookie = " + cookies.get(i));
}

 

LoginActivity: onResponse: cookie = PHPSESSID=q2i5cmhu493rp4lkj38flbnm0r; expires=Wed, 02 Sep 2020 11:57:06 GMT; path=/

 

로그로 확인해보면 기존에 없던 expires가 생겼습니다. 실제로 안드로이드 앱을 강제로 종료시켜도 세션이 유지되네요. 이제 로그인 세션 문제는 해결될까요? 좀 더 지켜보겠습니다.

 

참고로 AVD를 재부팅해도 로그인 세션이 유지가 되네요~! 아마도.. 안드로이드 앱에서 쿠키가 파일로 저장되기 때문에 그런 것 같습니다. 재부팅을 하더라도 쿠키 파일에는 정보가 남아있어서 그 정보를 가지고 오는 것 같네요.

 

*2020년 9월 2일 추가

서버에서 세션 파일이 잘 유지되나 싶더니.. 갑자기 거의 대부분의 세션 파일이 삭제된 것을 확인했습니다.

이렇게 세션 파일이 삭제되면.. 사용자는 로그인이 끊긴 것과 같은 현상을 겪어서.. 앱 종료 후 다시 로그인을 해야합니다.

음.. 일단 최신 파일과 가장 오래된 파일의 시간을 비교해보면.. 1시간 20분 정도되네요.

 

php -r 'echo ini_get("session.gc_maxlifetime"), "\n";'

 

위의 간단한 명령어로 다시.. 세션 파일 삭제 주기를 알아봤습니다.

지난번에 세션 파일 삭제 주기를 259200(초)로 늘렸었는데 그대로 값이 나옵니다.

그런데 왜.. 3일(=259200초)이 되지도 않은 최신 세션 파일들이 삭제가 됐을까요?

 

<?php
phpinfo();
?>

php를 사용해보신 분들이라면.. phpinfo()함수에 대해 들어본 적이 있을 것입니다. 위와 같이 파일을 만들고.. 해당 파일에 접속하면 php 서버의 여러 설정 값들을 볼 수 있습니다. 이 파일에 외부인이 접근하면 php서버의 설정 값들이 노출되기 때문에.. 해킹에 악용될 수 있으니 주의해야 합니다.

 

혹시나해서.. 위 파일을 만들고 접속을 해봤습니다.

아니나 다를까.. 현재 서버에서 적용되고 있는 세션 파일의 유지 시간은 1440초(24분)인 것 같습니다.

 

https://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime

php 공식 사이트에 8년 전에 누군가가 쓴 답글이 있습니다.

 

max value for "session.gc_maxlifetime" is 65535. values bigger than this may cause  php session stops working.

 

흠.. session.gc_maxlifetime의 최대값이 65535라고 해서.. 259200이던 값을 65535로 변경하고 apache 서버를 재시작해봐도.. 효과는 없습니다.

 

몇 가지 삽질을 더 한 후에.. 재부팅이 제대로 적용은 되는 것인가? 의문이 들었습니다.

그래서 aws lightsail 홈페이지에 접속한 후.. 완벽한? 재부팅을 했습니다.

참고로.. 그냥 재부팅 버튼을 누르면.. 제대로 재부팅이 되질 않습니다.

인스턴스를 종료한 후에.. 다시 시작 버튼을 눌러야 완전 재부팅이 됩니다.

인스턴스 종료에 한.. 2~3분 정도 걸리네요.

 

처음에는 재부팅 버튼 눌렀던 기록도 남아있습니다. 재부팅 버튼을 누르면.. 1~2초만에 동작이 완료되는데 ㅎㅎ;; 아무래도 얕은 재부팅 같네요.

완전 재부팅을 하고하니.. 설정값이 변경된 것을 확인할 수 있었습니다!!

 

이제 다시 session.gc_maxlifetime의 값은 259200으로 변경하고.. 서버를 완전 재부팅 하겠습니다.

session.gc_maxlifetime의 최대값이 겨우 65535라고 하는데.. 8년 전의 의견이니.. 적어도 지금은 개선되지 않았을까요? 

 

다시 aws lightsail 콘솔에서 서버를 중지하고 시작했습니다. 이번에는 금방되네요.

다행히 값은 정상적으로 보이네요. 이제.. 며칠동안 세션 파일 관찰하면서.. 실제로 잘 유지가 되는지 확인해봐야겠습니다.

작성자

Posted by 드리머즈

관련 글

댓글 영역