###### tags: `前後端系列`, `課程` # 11/30 前後端系列 - 用實際例子帶你暸解後端 [TOC] ## 前置準備 - VS Code - XAMPP (7.3.6 版本以上) :::warning 如果 MAC OS 使用者,在安裝XAMPP遇到 **「無法打開xampp,因為無法驗證開發者。」** 可以參考此篇[解決方法](https://app.yipee.cc/92743/%E3%80%90macos-%E6%95%99%E5%AD%B8%E3%80%91%E6%95%99%E4%BD%A0%E8%A7%A3%E6%B1%BA%E3%80%8C%E7%84%A1%E6%B3%95%E6%89%93%E9%96%8B-xxx%EF%BC%8C%E5%9B%A0%E7%82%BA%E5%AE%83%E4%BE%86%E8%87%AA%E6%9C%AA%E8%AD%98/) ::: - 到這邊下載上課要用的程式碼 [login-page](https://github.com/jovi920204/backend-course-material) ## 課程講義 ### Windows 1. 下載並安裝XAMPP: [下載連結](https://www.apachefriends.org/zh_tw/download.html) 2. 執行XAMPP, 並開啟Apache 和 Mysql 服務: ![](https://i.imgur.com/bLs09Tk.png) 3. 在 C:\xampp\htdocs 新增資料夾 ![](https://i.imgur.com/xOCU1lb.png) 4. 將上一次實作的檔案放入資料夾裡 ![](https://i.imgur.com/P1zXsmP.png) 5. 在瀏覽器輸入 http://localhost/"資料夾名稱"/, 能成功看到畫面代表成功。 ![](https://i.imgur.com/lfKnVft.jpg) 6. 在瀏覽器輸入 http://localhost/phpmyadmin/, 能成功看到畫面代表成功。 ![](https://i.imgur.com/VQm2eew.png) 7. 建立資料庫。 - 左方選擇"新增" ![](https://i.imgur.com/NnBbHvh.png) - 依照下方設定: 編碼記得 **utf8mb4\_unicode\_ci** ![](https://i.imgur.com/PIEzUJ9.png) - 成功 ![](https://i.imgur.com/aQtPpby.png) 8. 建立資料表 - ![](https://i.imgur.com/NevhChP.png) - ![](https://i.imgur.com/6X1oH7B.png) - 儲存後 ![](https://i.imgur.com/MtYy6RH.png) 9. 手動新增USER - ![](https://i.imgur.com/Yzkn1Tx.png) - 進入 https://phppasswordhash.com/ ![](https://i.imgur.com/Lj4UbyY.png) - 輸入密碼,複製HASH CODE。 ![](https://i.imgur.com/dirXDmt.png) - ![](https://i.imgur.com/bSeFbBe.png) - ![](https://i.imgur.com/BdQW42B.png) - 複製起來 ```sql= INSERT INTO `users` (`id`, `account`, `password`, `permission`) VALUES (NULL, 'admin', '$2y$10$MvOE/DStNVwKTfi1MdyIsOSqY9EGcL1zDUOgnc3bJg4kqoln6P7K6', '1'); ``` :::info auto_increment:自動新增流水號 ::: 10. ![](https://i.imgur.com/HsNzrAG.png) 11. 將style分出來 - ![](https://i.imgur.com/hCOGhdf.png) - ![](https://i.imgur.com/wlqvOgD.png) 12. 在 config.php 輸入 ```php= <?php class Config { public $db_host = "127.0.0.1"; public $db_acconut = "root"; public $db_password = ""; public $db_name = "gdsctest"; } ?> ``` 13. controller.php ```php= <?php require_once "./config.php"; class Controller { protected $config; protected $db; public function __construct() { $this->config = new Config(); $this->db = new PDO("mysql:host=" . $this->config->db_host . ";dbname=" . $this->config->db_name . ";charset=utf8", $this->config->db_account, $this->config->db_password); // ("mysql:host=127.0.0.1;dbname=blabla_gdsc;charset=utf8", "root", "") } } ``` 14. api.php ```php= <?php require_once "./controller.php" $controller = new Controller(); ?> ``` 15. 在 controller.php 建立 login 函數 - 建立 login 函數 ```php= public function login() { $account = $_POST["account"]; $password = $_POST["password"]; echo $account; echo $password; } ``` - 在 api.php 加上 login() ```php= <?php require_once "./controller.php"; $controller = new Controller(); $controller->login(); ?> ``` - 測試 ![](https://i.imgur.com/0CO3mNz.png) - 成功 ![](https://i.imgur.com/As0tJ9A.png) :::info 當送出表單時,如果聲明為 required 的欄位內容沒有填寫,會被瀏覽器提醒必填。 ![](https://i.imgur.com/6FqAJwr.png) ![](https://i.imgur.com/PQE6F5N.png) ::: 16. 產生在資料庫查詢的CODE - 在 phpmysql 中資料表的 "搜尋","account" 的運算子的部分改成 "=","值" 輸入 "admin" ![](https://i.imgur.com/wqIlCbR.png) - 複製他生成的語法 ```sql= SELECT * FROM `users` WHERE `account` = 'admin' ``` - 在 controller.php 中輸入 ```php= public function login() { $account = $_POST["account"]; $password = $_POST["password"]; $data = $this->db ->query("SELECT * FROM `users` WHERE `account` = '$account'")->fetchAll(); var_dump($data); } ``` - 測試 ![](https://i.imgur.com/GqwoAz4.png) - 成功 ![](https://i.imgur.com/kZRRcpb.png) 17. 資訊驗證 - 在 controller.php 中 的 login() 裡輸入 ```php= // 沒有資料 if(count($data) !== 1) { // die 執行後,不會再執行後面動作 die("no match"); } // password_verify: 前面明文,後面雜湊值 if(!password_verify($password, $data[0]["password"]) ) { // 驗證失敗 die("password not right"); } ``` - 建立 SESSION: 首先在 controller.php 的開頭加入 ```php= session_start(); ``` - 設定 SESSION: ```php= $_SESSION["id"] = $data[0]["id"]; $_SESSION["permission"] = (int)$data[0]["permission"]; echo $_SESSION["id"]; echo $_SESSION["permission"]; ``` - 將 `index.html` 改為 `index.php`,並確認 SESSION 在 `index.php` 中可以執行成功 - 在開頭加入 ```php= <?php session_start(); ?> ``` - 在 body 中任意位置加入 ```php= <?= $_SESSION["id"] ?> ``` 18. 設定權限及頁面跳轉 - 建立 management.php ```php= <?php session_start(); // SESSION 沒有設定 id 或 permission 的值 if(!isset($_SESSION["id"]) || !isset($_SESSION["permission"])) { // 跳轉至 index.php header("Location: index.php"); } // 沒有權限 if($_SESSION["permission"] !== 1) { // 跳轉至 normal.php header("Location: normal.php"); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Management Page</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Management Page</h1> </body> </html> ``` - 建立 normal.php ```php= <?php session_start(); // 如果SESSION 沒有設定 id 或 permission 就跳轉回 index.php if (!isset($_SESSION["id"]) || !isset($_SESSION["permission"])) { header("Location: index.php"); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>GDSC login</title> <link rel="stylesheet" href="./style.css"> </head> <body> <p>登入成功,但你沒權限QQ</p> </body> </html> ``` - 回到 controller.php 設定跳轉 ```php= if((int)$data[0]["permission"] === 1) { header("Location: management.php"); } else { header("Location: normal.php"); } ``` - 測試 ![](https://i.imgur.com/kNIhiHL.png) - 成功 ![](https://i.imgur.com/d9YN8Fx.png) 19. 登出 - normal.php / management.php ```php= <a href="api.php?function=logout">登出</a> ``` - api.php ```php= <?php require_once "./controller.php"; $controller = new Controller(); if (isset($_POST["function"])) { $data = $_POST; } else { $data = $_GET; } switch ($data["function"]) { case 'login': $controller->login(); break; case 'logout': $controller->logout(); break; } ``` - index.php ```php= <div class="fcc field"> <input required placeholder="username" type="text" name="account"> <input required placeholder="password" type="password" name="password"> <input type="hidden" name="function" value="login"> <input type="submit"> </div> ``` - controller.php ```php= public function logout() { // 刪除 session 的 id 及 permission unset($_SESSION["id"]); unset($_SESSION["permission"]); // 跳轉至原先的登入頁面 header("Location: index.php"); } ``` 20. 新增使用者 (Optional) - controller.php ```php= public function add_user() { $account = $_POST["account"]; $password = password_hash($_POST["password"], PASSWORD_DEFAULT); $permission = $_POST["permission"]; $data = $this->db->query("SELECT * FROM `users` WHERE `account` = '$account'")->fetchAll(); if (count($data) !== 0) { die("duplicated username"); } $this->db->query("INSERT INTO `users` (`account`, `password`, `permission`) VALUES ('$account', '$password', '$permission');"); } ``` - api.php ```php= switch ($data["function"]) { case 'login': $controller->login(); break; case 'logout': $controller->logout(); break; case 'add_user': $controller->add_user(); break; } ``` - management.php ```php= <input type="number" placeholder="0 => 一般使用者, 1 => 管理員" name="permission" min="0" max="1" required> <input type="hidden" name="function" value="add_user"> ``` --- ### Mac 1. 下載並安裝XAMPP: [下載連結](https://www.apachefriends.org/zh_tw/download.html) 2. 點到 Manage Serves 開啟Apache 和 Mysql 服務: ![](https://i.imgur.com/RysdN7X.png) 3. 在 Applications >> XAMPP\htdocs 中新增資料夾 4. 將上一次實作的檔案放入資料夾裡 5. 步驟 5 後請看 windows :::info 如果看不到錯誤訊息,請到 XAMPP/etc 中找到 php.ini 檔案 將 `display_errors=Off` 改成 `display_errors=On` :::