Session

Session

2019/10/20 (增補內容)

簡介

上週我們學到利用query string及$_GET來傳資料。

login.php

<?php
$message = isset($_GET["msg"])? "帳號密碼錯誤</br>" : "";
?>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

 <form action="login_process.php" method="post">
  <?=$message?>
  帳號: <input type="text" name="account"><br>
  密碼: <input type="password" name="password"><br>
  <input type="submit" value="登入">
 </form>

</body>

</html>

我們在login_process.php利用query string把

<?php
if ($_POST["account"] == "root" && $_POST["password"] == "password" ) {
  header("Location: success.php?account=root");
}
else {
  header("Location: login.php?msg=error");
}
?>

success.php

<?php
echo "welcome, ".$_GET["account"]."!<p>";
echo "<a href='login.php'>login.php</a>"
?>

不過,這會有一個問題: 萬一success.php一定要被驗證過,那我們要如何處理? 第一個想到的解決方法是在success.php加入檢查機制:

<?php
if (isset($_GET["account"])){
  echo "welcome, ".$_GET["account"]."!<p>";
  echo "<a href='login.php'>login.php</a>";
}
else {
  header("Location: login.php");
}

?>

可是,萬一要是被發現是利用?account=root,使用者是可以在瀏覽器直接打:

http://localhost/web/success.php?account=root

就會發生沒有通過登入也可以進入系統的問題了!! 那怎麼辦呢?!

Session

  • 當我們登入系統之後,系統記得我們是誰,主要就是靠session。sessions所儲存的就是個人化的資料內容,例如,帳號。session所儲存的內容會一直保留到瀏覽器關閉為止。session的內容是個人化的,不同人登入會使用不同的session。
  • PHP 7 Sessions

我們來試試看,改寫原本的登入頁面,當登入成功之後,就利用$_SESSION["account"]記住帳號。這樣做還有另一個好處,在其他頁面也可以取得session的資料。

login_process.php

<?php
if ($_POST["account"] == "root" && $_POST["password"] == "password" ) {
 session_start();
 $_SESSION["account"] = $_POST["account"];
 header("Location: success.php");
 
}
else {
 header("Location: login.php?msg=error");
}
?>

如果我們希望如果沒有透過登入就無法進入這個頁面,那就要多一些檢查

success.php

<?php
session_start();
if (isset($_SESSION["account"])){
 echo "welcome, ".$_SESSION["account"]."!<p>";
 echo "<a href='login.php'>login.php</a><p>";
 echo "<a href='success2.php'>success2.php</a>";
}
else {
 header("Location: login.php");
}

?>

這樣還有另一個好處,就是其他頁面也可以取得session的內容。

success2.php

<?php
session_start();
if (isset($_SESSION["account"])){
 echo "welcome, ".$_SESSION["account"]."!<p>";
 echo "<a href='login.php'>login.php</a><p>";
 echo "<a href='success.php'>success.php</a>";
}
else {
 header("Location: login.php");
}

?>

萬一使用者把頁面關了,下個使用者可以直接打網址也就可以不用登入就直接進入系統,所以,一定還要加個登出的頁面:

logout.php

<?php
session_start();
unset($_SESSION["account"]);
header("Location: login.php");
?>

也可以使用session_unset()或session_destroy() (詳參: 基於session_unset與session_destroy的區別詳解)

logout.php

<?php
session_start();
session_destroy();
header("Location: login.php");
?>

修改一下success.php

<?php
session_start();
if ($_SESSION["account"]){
  echo "welcome!".$_SESSION["account"]."<p>";
  echo "<a href='logout.php'>Logout</a><p>";
  echo "<a href='login.php'>login.php</a>";
  echo "<a href='success2.php'>success2.php</a>";
}
else {
  header("Location: login.php");
}

?>

session是屬於個人的,可以試著去連別人的程式,就會發現,不同人執行同一個程式,互相是不會干擾的。

該如何找到我電腦的IP位址 (Windows XP, Vista, 7, 8,10, Mac)?

  • For Windows 10
  • 方式1
    • 步驟1:按Windows鍵+R,然後會出現執行框,輸入控制台(control panel)並按Enter鍵。
    • 步驟2:點選網路和網際網路(若沒找到可跳過此項)>網路和共用中心>變更介面卡設定。
    • 步驟3:右鍵點選您的區域連線(乙太網路)圖示狀態,選取詳細資料您將會看到電腦的IP位址。
  • 方式2
    • 步驟1:右鍵點選螢幕右下角電腦圖示的開啟網路和網際網路設定。
    • 步驟2:點選乙太網路,並選取畫面右側的變更介面卡選項。
    • 步驟3:右鍵點選您的區域連線(乙太網路)圖示狀態,選取詳細資料您將會看到電腦的IP位址。

儲存form的輸入值

可以利用session將$_POST內容(從register.php傳過來的內容)儲存起來:

register_process.php

<?php
session_start();
$_SESSION["post"] = $_POST ?? [];

?>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>
 <a href="register_clear.php">重新填寫</a><br>
 <a href="register.php">修改</a>

</body>

</html>

回到register.php就可以將內容取出,為避免第一次進入時的錯誤訊息,加了一些檢查邏輯。radio的做法比較複雜一點,不是單純的把值放進去,而是要判斷何時要有"checked"。

<?php
session_start();
$postData = $_SESSION["post"] ?? [];
$name = $postData["name"] ?? "";
$email = $postData["email"] ?? "";
$website = $postData["website"] ?? "";
$comment = $postData["comment"] ?? "";
$gender = $postData["gender"] ?? "";

$maleChecked = ($gender=="male")?"checked":"";
$femaleChecked = ($gender=="female")?"checked":"";
$otherChecked = ($gender=="other")?"checked":"";

?>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

 <form action="register_process.php" method="post">
  Name: <input type="text" name="name" value="<?= $name?>"><br>

  E-mail: <input type="text" name="email" value="<?= $email?>"><br><br>

  Website: <input type="text" name="website" value="<?= $website?>"><br>

  Comment: <textarea name="comment" rows="5" cols="40"><?= $comment?></textarea><br>

  Gender:
  <input type="radio" name="gender" <?=$femaleChecked?> value="female">Female
  <input type="radio" name="gender" <?=$maleChecked?> value="male">Male
  <input type="radio" name="gender" <?=$otherChecked?> value="other">Other
  <br>
  <input type="submit" value="送出">

 </form>

</body>

</html>

清除內容

<?php
session_start();
unset($_SESSION["post"]);
header("Location: register.php");

?>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

 <a href="register.php">重新輸入</a>

</body>

</html>

** 作業 **

  • 更改第三週的作業,利用session暫存使用者的姓名,而不是使用URL及$_GET傳變數,也請確保沒有登入成功是無法進入下一頁,也加一個登出的功能。
  • 讓使用者可以回頭修改是否要繳會費以及想參加的活動,要利用session記住使用者所輸入的內容,並且要正確的顯示在介面上。 (挑戰題)

$_GET、$_POST、$_SESSION的比較

在php裡,不同的php頁面跟頁面之間的變數是無法共用的,所以,必須要靠$_GET、$_POST或$_SESSION。

$_GET跟$_POST主要是利用HTTP GET及HTTP POST傳遞變數。

HTTP POST一般而言是透過HTML form,傳送資料,HTTP GET可以利用url query string也可以利用HTML form。

$_GET

http://localhost/welcome_get.php?name=ben&email=benwu@im.fju.edu.tw

在welcome_get.php裡,利用$_GET取得資料。

<html>
<body>

Welcome <?php echo $_GET["name"]; ?><br>
Your email address is: <?php echo $_GET["email"]; ?>

</body>
</html>

當我們使用html form的時候,當method設定為get,或沒有寫method時,就是將form的內容透過HTTP GET送到welcome_get.php,雖然一般不會這麼用,但萬一忘了寫method時,就會被預設為GET了。

welcome_get.html

<html>
<body>

<form action="welcome_get.php" method="get">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>

</body>
</html>

或者,沒有指定method。

<html>
<body>

<form action="welcome_get.php">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>

</body>
</html>

在welcome_get.php裡,利用$_GET取得資料。

<html>
<body>

Welcome <?php echo $_GET["name"]; ?><br>
Your email address is: <?php echo $_GET["email"]; ?>

</body>
</html>

$_POST

如果是使用post

welcome_post.html

<html>
<body>

<form action="welcome_post.php" method="post">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>

</body>
</html>

在welcome_post.php裡,利用$_POST取得資料。

<html>
<body>

Welcome <?php echo $_POST["name"]; ?><br>
Your email address is: <?php echo $_POST["email"]; ?>

</body>
</html>

$_SESSION

$_SESSION的運作原理跟HTTP GET及HTTP POST是完全不同的,HTTP GET及HTTP POST是從資料把browser端送到server端,但是,$_SESSION則一直是儲存在server端,另一個差別是,$_GET及$_POST只在接收頁有效,到下一頁就無效了。但是$_SESSION只要被設定了,除非是時間到了或者是被清除了,否則就一直可以取得 (詳參: PHP 7 Sessions)。

設定$_SESSION變數

 session_start();
 $_SESSION["account"] = $_POST["account"];

取得$_SESSION變數

 session_start();
 $account = $_SESSION["account"];

清除特定session內容:

 session_start();
 unset($_SESSION["account"]);

清除session內所有的內容:

// remove all session variables
session_unset();

刪除整個session:

// destroy the session
session_destroy();