메뉴 건너뛰기

자료실

DATA

PHP 7.3 이상

세션은 session.cookie_secure = true; session.cookie_samesite = "None"; 만으로 해결됩니다.

이외의 쿠키가 타 사이트에서 넘어올 때도 살아있어야 하면 setcookie() 시 $options 변수에 세팅합니다. [매뉴얼]

session_start_samesite()

session_start() 대신 session_start_samesite() 를 사용합니다.

PHP 7.3 이상에서 session.cookie_secure = true; session.cookie_httponly = false; session.cookie_samesite = "None"; 한 것과 동일한 효과를 냅니다.

PHP 7.3 이상으로 업데이트한 이후에는 session_start() 로 치환 가능합니다.

http 접속시 쿠키가 secure 로 구워지지 않으며, 기존에 쿠키가 있을 경우 session_start() 시에도 새로 굽지 않기 때문에 로그인 같은 곳에서 session_regenerate_id() 를 해서 쿠키를 다시 굽는 과정이 필요하고, session_regenerate_id_samesite() 로 대체할 수 있습니다.

if(!function_exists('session_start_samesite')) {
	function session_start_modify_cookie()
	{
		$headers = headers_list();
		krsort($headers);
		foreach ($headers as $header) {
			if (!preg_match('~^Set-Cookie: PHPSESSID=~', $header)) continue;
			$header = preg_replace('~; secure(; HttpOnly)?$~', '', $header) . '; secure; SameSite=None';
			header($header, false);
			break;
		}
	}

	function session_start_samesite($options = [])
	{
		$res = session_start($options);
		session_start_modify_cookie();
		return $res;
	}

	function session_regenerate_id_samesite($delete_old_session = false)
	{
		$res = session_regenerate_id($delete_old_session);
		session_start_modify_cookie();
		return $res;
	}
}

setcookie_samesite()

세션 외 쿠키도 타도메인간 이동에 필요할 경우에 사용합니다.

setcookie() 대신 setcookie_samesite() 를 사용합니다.

PHP 7.3 이상의 setcookie() 와 동일하게 $options 로 세팅할 수 있습니다.

PHP 7.3 이상으로 업데이트한 이후에는 setcookie() 로 치환 가능합니다.

오류처리시 원래의 E_WARNING 을 낼 수 없어 E_USER_WARNING 으로 대체했으니 set_error_handler() 를 정의해서 이용한다면, 해당 부분을 체크해야 합니다.

if(!function_exists('setcookie_samesite')) {
	function setcookie_samesite($name, $value = '', $expires = 0, $path = '', $domain = '', $secure = false, $httponly = false, $samesite = '')
	{
		if(is_array($expires)) {
			$e = $expires;
			foreach(['expires', 'path', 'domain', 'secure', 'httponly', 'samesite'] as $key) {
				if(isset($e[$key])) $$key = $e[$key];
			}
		}
		if (preg_match('~[=,; \t\r\n\x0b\x0c]~', $name)) {
			trigger_error('Cookie names cannot contain any of the following \'=,; \t\r\n\013\014\'', E_USER_WARNING);
			return false;
		}
		if (preg_match('~[,; \t\r\n\x0b\x0c]~', $path)) {
			trigger_error('Cookie paths cannot contain any of the following \',; \t\r\n\013\014\'', E_USER_WARNING);
			return false;
		}
		if (preg_match('~[,; \t\r\n\x0b\x0c]~', $domain)) {
			trigger_error('Cookie domains cannot contain any of the following \',; \t\r\n\013\014\'', E_USER_WARNING);
			return false;
		}
		$values = [];
		if (empty($value)) {
			$values[] = $name . '=delete';
			$values[] = 'expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0';
		} else {
			$values[] = $name . '=' . urlencode($value);
			if ($expires != 0) {
				$values[] = 'expires=' . substr(gmdate('r', $expires), 0, -5) . 'GMT';
				$values[] = 'Max-Age=' . ($expires - time());
			}
		}
		if ($path) $values[] = 'path=' . $path;
		if ($domain) $values[] = 'domain=' . $domain;
		if ($secure) $values[] = 'secure';
		if ($httponly) $values[] = 'HttpOnly';
		if ($samesite) $values[] = 'SameSite=' . $samesite;
		header('Set-Cookie: ' . implode('; ', $values), false);
		return true;
	}
}

form submit redirect

타도메인에서 넘어온 후 사이트 내에서 페이지 이동이 일어나면 쿠키가 살아나는점을 이용하는 임시방편입니다.

pg 에서 넘어오는 return url 같은 곳에 임시로 사용 가능합니다.

class XenoPostToForm
{
	public static function check() {
		return !isset($_COOKIE['PHPSESSID']) && count($_POST) && isset($_SERVER['HTTP_REFERER']) && !preg_match('~^https://'.preg_quote($_SERVER['HTTP_HOST'], '~').'/~', $_SERVER['HTTP_REFERER']);
	}

	public static function submit($posts) {
		echo '<html><head><meta charset="UTF-8"></head><body>';
		echo '<form id="f" name="f" method="post">';
		echo self::makeInputArray($posts);
		echo '</form>';
		echo '<script>';
				echo 'document.f.submit();';
				echo '</script></body></html>';
		exit;
	}

	public static function makeInputArray($posts) {
		$res = [];
		foreach($posts as $k => $v) {
			$res[] = self::makeInputArray_($k, $v);
		}
		return implode('', $res);
	}

	private static function makeInputArray_($k, $v) {
		if(is_array($v)) {
			$res = [];
			foreach($v as $i => $j) {
				$res[] = self::makeInputArray_($k.'['.htmlspecialchars($i).']', $j);
			}
			return implode('', $res);
		}
		return '<input type="hidden" name="'.$k.'" value="'.htmlspecialchars($v).'" />';
	}
}

if(XenoPostToForm::check()) XenoPostToForm::submit($_POST); // session_start(); 하기 전에
번호 제목 글쓴이 날짜 조회 수
44 [php ]두날짜 사이에 기간을 배열로 반환 하는 함수 소프터 2020.12.11 91
43 개인정보 보안관리 솔루션 가이드 소프터 2020.12.09 25
42 셀레리움을 이용한 로그인과 데이터 크롤링예제 윈도우 10 소프터 2020.12.07 64
41 파이어베이스 웹푸시 소프터 2020.11.28 96
40 리액트 웹뷰 멀티 팝업설정 소프터 2020.10.16 218
39 리액트 네이티브 스플레쉬 정리 소프터 2020.08.27 262
» chrome 80 SameSite cookie CORS 보안 변경사항 php 대응 소프터 2020.07.22 838
37 phpMyAdmin 접속이 localhost 가 아닐경우 설정법. 소프터 2020.07.16 72
36 [디장고] ubuntu 18.04 웹서버에 올리는법 소프터 2020.07.02 391
35 [장고] mysql 연결하기 우분투 18.04 소프터 2020.07.02 42
34 우분투에서 타임존 변경 소프터 2020.06.18 25
33 react-native-permissions NSBluetoothAlwaysUsageDescription 권한을 요청할떄 소프터 2020.06.10 87
32 리액트 블루투스 모듈 ios 에서 pod spec 소프터 2020.06.10 49
31 xcode 캐시 지우는법 소프터 2020.06.10 39
30 [REACT NATIVE] 패키지명, 번들명 변경하기 PACKAGE, BUNDLE [ANDROID, IOS] [2] 소프터 2020.05.29 993
29 mac 개발환경 구축 2020 5 월 버전 소프터 2020.05.26 70
28 ios 스플레쉬 이미지 중앙정렬 소프터 2020.05.26 36
27 윈도우 에서 expo expo build : ios 실행법 소프터 2020.05.15 20
26 컴퓨터 밴치마크 게임 소프터 2020.05.12 20
25 아파치로그 실시간확인 소프터 2020.04.02 28