[Normaltic's 취업반 과제] jwt를 이용한 로그인

2024. 5. 3. 21:36정보보안 및 해킹/Normaltic's 취업반 과제

 

sign_up_func.php - 회원 가입 시 사용자가 입력한 정보들을 jwt로 변환시켜 정보에 함께 저장 (현재 평문 비밀번호를 통한 로그인 등 많은 것들이 엮여있어서 다른 요소를 삭제하지는 못함 / 삭제 예정)

[생략]

function try_signup($username, $userpassword, $userage, $useremail, $userphone)
{
  if (!connect_db()) {
    die("Connection failed: " . mysqli_connect_error());
}
  $table_name = "rame_table";
  $userpasswordhash = hash('sha256', $userpassword);
  $jwt = set_query_to_jwt($useremail, $userpassword, $username);

  // INSERT INTO `rame_table` (`idx`, `name`, `password`, `passwordhash`, `age`, `email`, `phone`, `jwt`) VALUES (NULL, 'dd', 'dd', 'dd', '22', 'dd@dd', '22', 'ddd');
  // $sql_query = "INSERT INTO $table_name VALUES (NULL, '$username', '$userpassword', '$userpasswordhash', '$userage', '$useremail', '$userphone', NULL)";
  


  $sql_query = "INSERT INTO $table_name VALUES (NULL, '$username', '$userpassword', '$userpasswordhash', '$userage', '$useremail', '$userphone', '$jwt')";
  
  // echo $jwt;
  $sql_res = mysqli_query(connect_db(), $sql_query);
  // var_dump($sql_res);
  
  if ($sql_res) {
    refresh_auto_indrement_num();
    header("location: index.php?login_id=" . $username);
    exit;
  }


}


[생략]

login.php - jwt login 버튼 추가 및 클릭 시 jwt_func.php에 있는 이벤트 발생

[생략]

require_once ('jwt_func.php');
require_once ('jwt.php');

[생략]

<button class="submit-button" name="jsonwebtokenlogin" value="jwtlogin">jwt Login</button><br>

[생략]

if(isset($_POST['jsonwebtokenlogin'])) {
        get_jwt_from_db($_POST['id'], $_POST['pass'], false, false);
      }
      
      [생략]

jwt.php - jwt를 제작하는 클래스 및 함수들. hasging과정과 dehashing과정이 있음

<?php
class JWT
{
    protected $alg;
    protected $secret_key;

//    생성자
    function __construct()
    {
        //사용할 알고리즘
        $this->alg = 'sha256';

        // 비밀 키
        $this->secret_key = "[비밀키]";
    }

//    jwt 발급하기
    function hashing(array $data): string
    {
        // 헤더 - 사용할 알고리즘과 타입 명시
        $header = json_encode(array(
            'alg' => $this->alg,
            'typ' => 'JWT'
        ));

        // 페이로드 - 전달할 데이터
        $payload = json_encode($data);

        // 시그니처
        $signature = hash($this->alg, $header . $payload . $this->secret_key);

        return base64_encode($header . '.' . $payload . '.' . $signature);
    }

//    jwt 해석하기
    function dehashing($token)
    {
        // 구분자 . 로 토큰 나누기
        $parted = explode('.', base64_decode($token));

        $signature = $parted[2];

        // 토큰 만들 때처럼 시그니처 생성 후 비교
        if (hash($this->alg, $parted[0] . $parted[1] . $this->secret_key) != $signature) {
            return "시그니쳐 오류";
        }

        // 만료 검사
        $payload = json_decode($parted[1], true);
        if ($payload['exp'] < time()) { // 유효시간이 현재 시간보다 전이면
            return "만료 오류";
        }

        /*
         *
         * 기타 토큰 확인 작업
         *
         */

        return json_decode($parted[1], true);
    }
}
?>

jwt_func.php - 사용자로부터 입력받은 정보를 hashing하여 jwt로 만드는 함수와, jwt를 dehashing하여 다시 원래의 정보로 복구하는 과정이 있음

<?php
require_once('connect_db.php');
require_once('jwt.php');
require_once('login_func.php');

function set_query_to_jwt($email, $password, $user_id)
{
  
$jwt = new JWT();

// $email = "simple@mail.com";
$email = base64_encode($email); // .이 들어가도 JWT가 분리되지 않기 위한 base64 인코딩

// $password = "password..1234";
$password = base64_encode($password); // .이 들어가도 JWT가 분리되지 않기 위한 base64 인코딩


// 유저 정보를 가진 jwt 만들기
$token = $jwt->hashing(array(
    'exp' => time() + (360 * 30), // 만료기간
    'iat' => time(), // 생성일
    'id' => $user_id,
    'email' => $email,
    'password' => $password
));

// var_dump($token);
return $token;
}

function get_jwt_from_db($username, $userpass, $is_hash, $_is_separate)
{
  
  $sql_res =  find_name_use_sql($username, $userpass, $_is_separate);
  $sql_row = mysqli_fetch_array($sql_res);

  $jwt = new JWT();
  $email = base64_encode($sql_row['email']); // .이 들어가도 JWT가 분리되지 않기 위한 base64 인코딩
  $password = base64_encode($userpass); // .이 들어가도 JWT가 분리되지 않기 위한 base64 인코딩
  // $jwt = $sql_row['jwt'];
   
  $token = set_query_to_jwt($sql_row['email'], $userpass, $username);
  
  // jwt에서 유저 정보 가져오기
$data = $jwt->dehashing($token);

$parted = explode('.', base64_decode($token));

$payload = json_decode($parted[1], true);

// echo "<br/><br/>";
// echo "jwt: " .$token;
// echo "<br/><br/>";
// echo "id: " . $payload['id'];
// echo "<br/><br/>";
// echo "password: " . base64_decode($payload['password']);

//  login_check($payload['id'], base64_decode($payload['password']),  $is_hash, $_is_separate);
}
?>

 

 

ref. https://stickode.tistory.com/176

 

[PHP] JWT 구현하기

안녕하세요 이번 포스팅에서는 PHP로 JWT를 발급하고 JWT의 내용을 해석해보겠습니다. JWT란? JWT(JSON Web Token) 는 json 형식으로 되어있는 토큰입니다. 웹 전자 서명에 쓰이는 토큰으로 URL로 사용할 수

stickode.tistory.com