2022.12.12
PHP 프로젝트를 서버에 배포했다.
로컬에 배포했을 때는 페이지를 이동할 때 로그인 정보가 함께 넘어갔는데, 서버 배포 후에는 넘어가지지 않았다.
이 문제의 해결 방법과 그에 대한 설명을 정리하겠다.
1. 해결 방법
프로젝트 내 모든 파일의 PHP 영역 시작 태그(<?php) 밑에 아래 코드를 추가해 문제를 해결했다.
$_SESSION['로그인 정보'};
session_start(); // 세션 시작
2. 설명
2-1. 세션(Session)
세션은 쿠키와 함게 HTTP 프로토콜의 특성이자 약점을 보완하기 위해 사용된다.
HTTP(HyperText Transfer Protocol) 환경은 무상태 프로토콜stateless, 비연결성connectionless 특성을 가진다.
때문에 서버는 매번 클라이언트가 누구인지 확인해야 한다.
- 무상태 프로토콜Stateless
: 통신이 끝나면 서버가 클라이언트의 상태를 보존하지 않는다.
- 비연결성connectionless
: 클라이언트가 요청 후 응답을 받으면 연결을 끊는다.
세션과 쿠키는 웹 사이트의 여러 페이지에 걸쳐 사용되는 사용자 정보를 저장하는 방법이다.
또, 세션은 쿠키를 기반으로 한다.
세션은 사용자 정보를 서버 측에서 관리한다(쿠키는 사용자 정보를 브라우저에 저장한다).
서버에서는 클라이언트를 구분하기 위해 세션 ID를 부여하며, 웹 브라우저가 서버 접속을 종료할 때까지 인증 상태를 유지한다.
사용자에 대한 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지한다.
그런 이유로 동시 접속자가 많은 웹 사이트의 경우 서버에 과부하를 주어 성능이 저하될 수 있다.
사용 방법도 쉽기 때문에 로그인과 같은 인증 처리에 많이 사용된다.
2-2. 세션 사용 방법
2-2-1. 세션 시작하기
<?php
session_start();
PHP에서는 세션을 사용하기 위해 session_start()를 쓴다.
이미 세션이 생성되어 있다면 기존 세션을 사용하고, 사용자 정보가 웹 서버에 없을 경우에는 새로운 세션을 생성한다.
생성된 세션의 키 값은 브라우저의 개발자 도구를 통해 확인할 수 있다.
마우스 우클릭-검사-Network-Cookies
PHP에서 세션을 생성하면 PHPSESSID로 저장된다.
이름은 php.ini에서 변경 가능하다.
일시적인 변경을 위해서는 session_name('변경할 이름')을 사용한다.
이때, session_name()은 session_start()보다 위에 입력해야 한다.
session_start() 함수를 같은 파일에서 여러 번 실행하면 이미 세션이 실행되었다는 알림을 출력한다.
session_id() 함수를 사용하여 현재 생성된 세션이 있는지 확인한 후 세션을 시작하는 것이 좋다.
<?php
if(!session_id()) { // 발급된 세션 id가 있다면 세션의 id를, 없다면 false 반환
session_start(); // id가 없을 경우 세션 시작
}
2-2-2. 세션 변수 사용
<?php
//세션 시작
session_start();
//세션 변수 등록
$_SESSION['userName'] = 'tester';
$_SESSION['userPw'] = '1234';
//등록된 변수 사용
echo "userName 값: ".$_SESSION['userName']."<br/>";
echo "userPw 값: ".$_SESSION['userPw'];
세션을 사용하여 변수를 등록하려면 위처럼 $_SESSION['변수명'} = Data 를 입력하면 된다.
2-2-3. 세션 변수 해제
<?php
session_start(); // 세션 시작
//세션 변수 등록
$_SESSION['userName'] = 'tester'; // 세션 변수 등록
unset($_SESSION['userName']); // 등록된 변수 해제
세션에 등록된 변수를 해제할 때는 unset($_SESSION['변수명'])을 입력한다.
이를 사용하면 해당 변수 등록이 해제되어 사용할 수 없게 된다.
모든 변수를 해제하고 싶으면 session_unset() 함수를 사용한다.
세션을 완전히 종료하고 싶으면 session_destroy() 함수를 사용하여 세션 파일과 부라우저의 쿠키를 삭제한다.
2-2-4. 세션 변수 등록 여부 확인
<?php
session_start(); // 세션 시작
$_SESSION['userId'] = ''; // 변수 등록
if(!isset($_SESSION['userId'])) { // 변수 등록 여부 확인
$_SESSION['userId'] = 'data1';
echo '새로운 변수 생성';
} else {
$_SESSION['userId'] = 'data2';
echo '기존 변수 데이터 변경';
}
echo '<br/>'.$_SESSION['userId'];
isset() 함수를 사용하면 해당 변수가 등록되었는지 확인할 수 있다.
isset($_SESSION['변수명']) 형태로 사용한다.
해당 변수가 등록되면 true 값을, 등록되지 않으면 false 값을 반환한다.
위의 코드는 변수가 등록되지 않으면 data1을, 등록되면 data2를 저장하고 출력할 것이다.
2-2-5. 세션 id 변경
세션은 브라우저 쿠키에 등록된 id를 사용해 서버에 저장된 데이터에 접근한다.
그래서 세션 id를 탈취당하면 세션에 저장된 데이터들 또한 탈취 당할 위험이 커진다.
일반적으로 사용자의 인증정보 변동(로그인/로그아웃), 설정 변경 등 변경 사항이 있을 때 세션 id를 변경한다.
PHP에서는 session_regenerate_id() 함수를 사용해 새로운 id를 발급받아 쿠키를 생성한다.
<?php
session_start(); // 세션 시작
echo session_id(); // 현재 세션 id 확인
echo '<br/><br/>';
session_regenerate_id(); // 세션 id 신규 발급
echo session_id(); // 신규 발급된 id 확인
session_regenerate_id() 함수는 세션 id를 변경한 후 이전의 세션 데이터를 삭제하지 않는다.
id만 새로 발급해 데이터를 복제하는 방식이다.
그래서 서버에서 id는 다르지만 같은 데이터를 가진 세션 파일을 확인할 수 있다.
이전 데이터를 지우고 싶으면 session_regenerate_id(true) 형식으로 파라미터를 사용해 이전 세션 데이터를 삭제한다.
이렇게 하면 새로운 id가 발급되고, 이전의 세션은 완전히 삭제된다.
2-2-6. 세션 종료하기
브라우저 연결이 끊기면 자동적으로 세션 데이터가 삭제된다.
그러나 로그아웃 기능을 사용할 때는 사용자의 요청을 받아 세션을 종료해야 한다.
그럴 때는 session_destroy() 함수를 사용한다.
<?php
if (!session_id()) { // 세션 데이터에 접근하기 위해 세션 시작
session_start();
}
$_SESSION = array(); // 세션 데이터 빈 배열로 초기화
// 또는 session_unset(); 사용
if (ini_get("session.use_cookies")) { // 세션 ID 값이 저장되어 있는 쿠키 삭제
$params = session_get_cookie_params();
setcookie(
session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy(); // 세션 파일 삭제
session_destroy()는 현재 세션의 데이터가 저장된 파일을 삭제하는 함수다.
그러나 세션 ID 값이 들어 있는 쿠키는 그대로 남아있게 된다.
그래서 setcookie() 함수를 사용해 세션 ID가 저장된 쿠키를 강제로 만료시켜 삭제해야 한다.
또, session_destroy() 함수가 $_SESSION 변수까지 해제하는 것은 아니기 때문에 빈 배열을 넣어 초기화 시켜주어야 한다.
session_unset() 함수를 사용해도 같은 동작을 실행한다.
2-3. 세션 유지 시간
세션 유지 시간은 설정 파일인 php.ini에서 확인할 수 있다.
php의 기본 세션 유지 시간은 1440초(24분)다.
php의 세션 관리는 확률로 이루어진다.
gc_probability / gc_divisor 의 확률로 gc_maxlifetime에서 지정한 시간이 지난 세션 데이터를 삭제한다.
단순히 세션 유지 시간을 늘리고 싶다면 session.gc_maxlifetime 값을 올려주면 된다.
session.gc는 모든 세션의 생성 시간을 조회하는 방식이라 세션이 많이 생성되었을 경우 서버에 부담을 준다.
그래서 PHP 공식 문서에서는 UNIX 형태의 서버는 session.gc_probability의 값을 0으로 설정하고 예약 실행 스케쥴러인 cron을 사용해 수동으로 실행하는 편이 좋다고 말한다.
2-4. 추가 보안 설정
세션은 쿠키만 사용하는 것보다는 보안이 좋지만, 쿠키와 함께 사용하는 것이기 때문에 추가적인 설정이 필요하다.
비활성화 되어 있는 설정들을 아래처럼 활성화 시켜야 한다.
; 초기화 되지 않은 세션ID 생성 방지. URL로 세션ID 전달 방지
session.use_strict_mode = 1
; 쿠키만 사용하여 세션ID 저장. URL로 세션ID 전달 방지
session.use_only_cookies = 1
; 쿠키가 http 통신을 통해서만 전달되도록 설정. 자바스크립트에서 접근하는 것을 방지
session.cookie_httponly = 1
; https를 사용하는 경우 https만을 통해서 전달되도록 설정. 기본설정은 주석처리. 상황에 따라 설정
session.cookie_secure = 1
위의 설정 이상의 추가 보안 설정을 원한다면 PHP 공식 문서에서 권장하는 세션 설정을 참조해 설정하면 된다.
'PHP' 카테고리의 다른 글
[PHP] 라디오 버튼으로 값 체크하기 (0) | 2023.10.10 |
---|---|
[PHP] 라디오 버튼을 변경할 수 없게 막는 방법 (0) | 2023.10.10 |