자습

내가 만든 사이트에 세션, 로그아웃, DB 연동 파일 분리 적용하기

whydontyoushovel 2024. 11. 12. 02:59

 <현재 환경 세팅>

1. Virtual Box 7.1.4 + 우분투 리눅스 20.04

2. 우분투 APM (Apache2 + PHP + MySQL)

3. 기본 웹 루트 경로 /var/www/html

4. VScode SSH

5. 사진 등은 termius

 

 

 

충격적인 사실!!!!!!!!!!

 

phpsessid가 사용자의 로그인상태를 알려주는 척도가 아니란다.

너무 충격적이다..

 

이제껏 로그인한 후에 개발자도구를 이용해서 phpsessid가 생긴 거 보고 음~ 잘 로그인 되었군 허허 했는데

지금 확인해보니 login.php 페이지만 가도 phpsessid값이 발급된다...!!!!!!!!! 으악!!

 

phpsessid는 그냥 session_start(); 가 포함된 페이지에 접근한 사용자들에게 다 주는 거라고 한다..

일단 일련번호를 붙이는 느낌으로..

 

근데 이 세션 아이디를 발급받은 사용자가 로그인하면 말이 달라진다.

로그인 성공한 사용자의 세션아이디를 쿠키 헤더에 붙여서 다른 페이지를 요청하면 들어가지기 때문이다.

증거로 나는 방금 내 세션 아이디를 탈취했다.

 

 

세션아이디 탈취한 썰

더보기
더보기

어그로 끌어서 미안하다. 

 

방금 내 사이트에서 로그인하고 콘솔 창에서 console.log(document.cookie);를 하니까

뙇 phpsessid가 나오길래 그거 긁어다가

버프스위트에서 요청헤더에 붙여넣고 index.php 파일을 리피터로 요청했는데

 

응답요청 렌더링 결과엔 login.php 파일이 아니라

index.php 페이지가 아아아주 잘 나왔다. (엄마..저 제 지갑에 있는 돈을 훔쳤어요..)

 

근데 응답데이터를 렌더링한 결과는 미친 개딱딱한 정적 페이지라서 이용할 수가 없었다.

 

사이트를 사용하기 위한 용도는 아닌 건가..?

아니면 또 뭔가 조치를 취해야 그 세션아이디로 사이트를 이용할 수 있나?

(intercept로 하면 됨)

 

위에서 말했듯이 phpsessid 자체는 session_start();가 포함된 페이지를 요청한 사용자들에게 붙이는

단순 구별자 같은 거고

 

이 세션아이디를 가진 사람들이 로그인을 했느냐 마느냐는

세션id를 키값으로 세션 데이터를 조회해야 알 수 있는데

 

로그인 성공 시 부여했던 $_SESSION['id']와 같은 값들이 해당 세션id와 연결된 사용자의 세션 데이터로 저장된다고 한다.

 

 

정리하자면 phpsessid는 그냥 session_start();가 포함된 페이지를 방문한 사용자들에게 모두 발급하는 세션 아이디이지만

만약 그 사용자가 로그인에 성공하면 이미 받은 세션 아이디를 key로 id등을 세션 변수에 저장한다.

 

세션 데이터:    PHPSESSID    /    $_SESSION['id']    /    사이트 이용 중 받은 세션변수 등

↑ 

   다른 페이지를 요청한 사용자의

세션id를 키값으로 세션 데이터를 찾아서

   로그인 시 저장하는 세션변수( $_SESSION['id'] )가 발견되면

   그 페이지에 재로그인할 것을 요구할 필요가 없다.

 

그니까 다른 페이지에 접근하기 전에 $_SESSION['id']에 값이 없으면 login.php로 돌려보내는 것이다.

 

역시... 이해했다고 생각했는데 해보면 또 다르다..

 

 

 

 

♨ 하고 싶은 거 + 해야 하는 거

 

1. 로그인 성공 시 사용자 아이디를 세션 변수에 넣고

   그 세션 변수에 값이 있으면 다른 페이지 입장

   없으면 로그인 페이지로 리다이렉션 + 오류문 출력

 

2. 로그아웃 버튼 구현

    자바스크립트 이벤트 클릭 -> 로그아웃.php로 이동

    근데 이걸 js 파일이랑 php파일로 나눠서 함수로 처리하는 버전

 

3. 로그아웃 시 phpsessid 재발급 설정

 

4. 세션 유효시간 설정

    세션 쿠키 만료시간 설정

   근데 이걸 다른 파일에 만들어서 include나 require로 처리

 

5. DB연동 코드 require/include로 처리

 

 

 

 

 

1) 세션 변수로 로그인 유지하기

로그인할 때 로그인 성공 시 이거 넣고 리다이렉션. (login_proc.php에서 처리) 

회원가입할 때도 가입 완료후 바로 index로 갈 거면 이거 추가

    $_SESSION['id'] = $id;

 

 

index.php 페이지에 session_start(); 쓰고 받은 세션변수 값 없으면 alert 출력하고 페이지 읽지 마

          -> alert 창의 확인버튼 누르면 login.php로 리다이렉션

세션변수 값 있으면 index.php의 html코드 진행

<?php
session_start();
if(!isset($_SESSION['id'])) {

	echo "<script>
    alert('로그인이 필요한 서비스입니다.);
    window.location.href = 'login.php';
    </script>";
    
    exit;
    
} ?>    //이후 index.php의 html코드

 

이걸 필요한 페이지마다 추가 (게시물 업로드 페이지, 마이페이지 등등)

 

 

2) 로그아웃

㉮ index.php (등 로그아웃 버튼이 있는 모든 페이지에 아래 코드 필요)

<head>
	<script src="logout_func.js"></script>
</head>
<body>
	<button id="logout" onclick="logout()">로그아웃</button>
</body>

 

㉯ logout_func.js (버튼 요소의 클릭 이벤트와 php 파일을 잇는 다리 느낌)

function logout() {
	var http = new XMLHttpRequest();   //요청을 변수에 저장
    
    http.open('GET','logout.php',true);   //get방식으로 저 파일요청. 근데 비동기식으로
    http.onload = function() {        //서버가 요청에 응답하면 함수 실행
    	if(http.status === 200) {    //응답 상태가 200(요청 성공)이면
        	window.location.href = 'login.php';   //여기로 돌려
            exit;
        }
    }
    http.send();  //http.open요청 보냄.get요청은 url에 인자 있어서 () 상태로 보낸댜
}
                        //이런 걸 Ajax 요청이라 한다지..?
                        //새로고침 없이 비동기적으로 처리. 뭔가 안 기다리고 직접 요청하는 느낌

**비동기적 처리 : 다른 자바스크립트 코드 처리될 때까지 기다리지 않고 별동대 꾸려가지고 적진을 돌파하ㄴ..

**onload : 요청이 완전히 완료되었을 때만 실행

 

실제로는 open(요청 준비) -> send(요청 보냄) -> onload(응답 받고 함수 실행) 순으로 진행되는 건데

send는 오래 걸리기도 하고 응답 받으면 뭐 할 건지를 먼저 정해두는 게 비동기적(?)으로나 가독성 면에서 선호되는가봄 

ajax에서는 응답 받았을 때 실행할 로직을 요청 보내기 전에 미리 준비하는 게 직관적이라고 평가되는 듯! 

 

㉰ logout.php

<?php
session_start();
            
session_unset();

session_regenerate_id();

if(ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(),'',time() - 42000,$params['path'],$params['domain'],$params['secure'],$params['httponly']);
}

session_destroy();

header("location: login.php");
exit;

?>

세션 값 받으려고 일단 session_start();

세션 변수들 다 삭제

기존에 이 사용자가 쓰던 세션 아이디 삭제하고 새로운 세션 아이디 생성

쿠키 삭제 코드 : 세션이 쿠키를 사용 중이면 세션 쿠키 파라미터를 받아서 쿠키값을 설정함.

                        세션 이름(나는 phpsessid), 쿠키에 들어가는 값, 시간 만료시키기, 등등 파라미터들

세션 완전 종료. 서버에 남은 세션 데이터 모두 삭제(물론 로그아웃 한 사용자에 해당하는 데이터임)

다 완료하고 로그인 페이지로 이동

 

 

 

3) 세션ID 재발급

2번에서 함

session_regenerate_id(true);

true값이 있어야 이전에 쓰던 세션 아이디가 삭제된다고 함.

true 안 쓰면 이전에 쓰던 세션 아이디를 재활용하고.

 

phpsessid 값 자체가 로그인 정보를 가지지 않는다면 왜 굳이 재발급할 필요가 있을까 궁금했는데

세션 고정 공격이라는 게 또 있다 함.

 

세션 값 일단 탈취해서 다른 사람한테 그 세션 아이디 주고

그 사람이 그 세션 아이디를 가진 채로 로그인하길 기다리는 그런 공격인 듯

 

세션 아이디 재발급은 그런 공격을 예방하기에 좋다고 함.

 

 

 

4) 세션, 쿠키 유효 시간

㉮ 세션 유효 시간 설정

ini_set('session.gc_maxlifetime', 3600); // 서버에서 세션 데이터가 유지되는 시간 (초 단위)
session_start();                         // 1시간 유지

 

㉯ 세션 쿠키 만료 시간 설정

session_start([
    'cookie_lifetime' => 3600 // 쿠키가 유지되는 시간 (초 단위, 예: 1시간 = 3600초)
]);                            // 1시간 유지

 

난 한 세시간 해둘까. 그럼 10800을 3600대신 써 넣으면 된다.

 

이것도 마찬가지로 파일로 따로 분리해서 require나 include로 포함시키는 방법도 있다.

 

 

5) DB 연동 코드 따로 빼기

㉮ db_connection.php

<?php

define('DB_SERVER', 'localhost');
define('DB_USER', '안알랴줌');
define('DB_PASS', '안알랴줌222');
define('DB_NAME', 'registration');

$db_conn = mysqli_connect(DB_SERVER,DB_USER,DB_PASS,DB_NAME);

?>

 

㉯ db 필요한 파일 (로그인, 회원가입 관련 페이지 중 연동한 파일)에 추가

<?php
	require 'db_connection.php';
?>

 

 

 

 

 

그래서 게시판 언제 만듦..?

 

'자습' 카테고리의 다른 글

웹 개발: 마이페이지  (2) 2024.11.25
CTF: 어드민은 내 것이다.  (0) 2024.11.23
웹 개발: 게시판 - 글 작성  (2) 2024.11.13