2024/11/21
2024/11/27 (更新內容)
在個資法的要求下,個人機敏資料在資料庫中都必須加密。最簡單的方式就是利用password_hash(),產生出雜湊後的密碼之後,就可以儲存在資料庫裡,儲存後不再解密,而是利用password_verify(),去驗證是否與原本的密碼一致。**注意** password_hash()所產生的雜湊密碼每次產生的內容都不會一樣,這樣就能避免有人用password_hash()比對密碼內容。因為password不需要還原,所以,可以利用雜湊來進行加密,但是,如果是機敏資料,那就要利用對稱或非對稱加密演算法來進行加密了。
使用對稱加密演算法
加密與解密用同樣的金鑰
使用非對稱加密演算法
加密與解密用同樣的金鑰:公鑰、私鑰
使用雜湊函數
不進行解密
因為密碼經過hash之後,長度至少超過60個字,user資料表裡密碼的長度要改為255。
可利用以下程式將目前的密碼全數加密:
<?php
require_once 'db.php';
//利用mysql_i procedural的方式,將資料庫裡的明碼密碼改成hash密碼
$sql = "select * from user";
$result = mysqli_query($conn, $sql);
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$account = $row['account'];
$plainPassword = $row['password'];
$hashedPassword = password_hash($plainPassword, PASSWORD_DEFAULT);
$updateSql = "UPDATE user SET password='$hashedPassword' WHERE account='$account'";
mysqli_query($conn, $updateSql);
}
echo "密碼成功更新";
} else {
echo "Error: " . mysqli_error($conn);
}
mysqli_close($conn);
?>
請修改對應的程式,例如: login_process.php/login.php
if($row = mysqli_fetch_assoc($result)) {
if (password_verify($password, $row["password"])){
echo "登入成功";
$_SESSION["account"]=$account;
header("Location: index.php");
}
else {
echo "登入失敗";
header("Location: login.php?msg=帳密錯誤");
}
}
else {
echo "登入失敗";
header("Location: login.php?msg=帳密錯誤");
}
還有哪些程式要改?
當資料表之間建立關聯之後,新增或修改資料就必須要注意資料表之間的關係。
在practice資料表中,新增三個資料表:product、sales_order、sales_order_detail,讓使用者可以在同一個訂單中可以購買多個商品。
-- 建立 product 資料表
CREATE TABLE product (
product_id INT AUTO_INCREMENT PRIMARY KEY, -- 商品ID
product_name VARCHAR(255) NOT NULL, -- 商品名稱
price INT NOT NULL, -- 商品價格
stock INT NOT NULL -- 庫存數量
);
INSERT INTO `product` (`product_id`, `product_name`, `price`, `stock`) VALUES
(1, 'iPad Pro', 34900, 10),
(2, 'iPad Air', 19900, 10),
(3, 'iPad', 11900, 5),
(4, 'iPad mini', 16900, 10),
(5, 'iPhone 16 Pro', 36900, 10),
(6, 'iPhone 16', 29900, 10),
(7, 'iPhone 15', 25900, 10),
(8, 'iPhone 14', 21900, 10),
(9, 'iPhone SE', 14900, 10),
(10, 'MacBook Pro', 54900, 10),
(11, 'MacBook Air', 32900, 10),
(12, 'AirPods 4', 4490, 20),
(13, 'AirPods Pro 2', 7490, 20),
(14, 'AirPods Max', 17900, 20),
(15, 'Apple Watch SE', 7900, 20),
(16, 'Apple Watch Series 10', 13500, 20),
(17, 'Apple Watch Ultra 2', 27900, 10);
-- 建立 sales_order 資料表
CREATE TABLE sales_order (
order_id INT AUTO_INCREMENT PRIMARY KEY, -- 訂單ID
user_account VARCHAR(20) NOT NULL, -- 關聯使用者account
order_date DATETIME DEFAULT CURRENT_TIMESTAMP, -- 訂單日期
FOREIGN KEY (user_account) REFERENCES user(account) ON DELETE CASCADE -- 外來鍵: 關聯 user
);
-- 建立 sales_order_detail 資料表
CREATE TABLE sales_order_detail (
order_detail_id INT AUTO_INCREMENT PRIMARY KEY, -- 訂單明細ID
order_id INT NOT NULL, -- 關聯訂單ID
product_id INT NOT NULL, -- 關聯商品ID
quantity INT NOT NULL, -- 購買數量
FOREIGN KEY (order_id) REFERENCES sales_order(order_id) ON DELETE CASCADE, -- 外來鍵: 關聯 sales_order
FOREIGN KEY (product_id) REFERENCES product(product_id) ON DELETE CASCADE -- 外來鍵: 關聯 product
);
先讀取產品資料庫的內容。
productQuery.php
<?php
require_once "header.php";
try {
require_once 'db.php';
$sql = "select * from product";
$result = mysqli_query($conn, $sql);
?>
<div class="container">
<input class="btn btn-secondary" value="結帳">
<div id="cart"></div>
<div class="row row-cols-1 row-cols-md-3 g-4">
<?php
while($row = mysqli_fetch_assoc($result)) {?>
<div class="col">
<div class="card">
<div class="card-body">
<h5 class="card-title"><?=$row["product_name"]?></h5>
<p class="card-text">NT$<?=$row["price"]?></p>
<button class="btn btn-primary">加入購物車</button>
</div>
</div>
</div>
<?php
}
?>
</div>
</div>
<?php
mysqli_close($conn);
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
require_once "footer.php";
?>
可以利用javascript來寫個陽春的購物車,記住消費者想要的商品。這樣的作法,好處是都在瀏覽器端操作,並沒有送到伺服器端,但是這樣的作法有個缺點,只要重整頁面,購物車就會消失。
以javascript寫購物車其實是想以這個例子告訴大家,PHP跟Javascript是可以一起運作的,只是大家要記得javascript是在瀏覽器上執行,PHP是在伺服器端執行,運作機制不同。PHP裡的變數可以直接放在javascript裡,但是javascript裡的變數則需要透過GET或POST傳給PHP。
<?php
require_once "header.php";
try {
require_once 'db.php';
$sql = "select * from product";
$result = mysqli_query($conn, $sql);
?>
<script>
cart = [];
function addToCart(pid){
cart.push(pid);
document.getElementById("cart").innerText = "購物車內容:"+cart.join(",");
// alert("已加入購物車"+cart.join(","));
}
function showCart(){
window.location.href = "checkout.php?cart="+cart.join(",");
}
</script>
<div class="container">
<input class="btn btn-secondary" onclick="showCart()" value="結帳">
<div id="cart"></div>
<div class="row row-cols-1 row-cols-md-3 g-4">
<?php
while($row = mysqli_fetch_assoc($result)) {?>
<div class="col">
<div class="card">
<div class="card-body">
<h5 class="card-title"><?=$row["product_name"]?></h5>
<p class="card-text">NT$<?=$row["price"]?></p>
<button class="btn btn-primary" onclick='addToCart(<?=$row["product_id"]?>)'>加入購物車</button>
</div>
</div>
</div>
<?php
}
?>
</div>
</div>
<?php
mysqli_close($conn);
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
require_once "footer.php";
?>
checkout.php,利用$_GET取得購物車內容。
<?php
echo $_GET["cart"];
?>
產生訂單時,需要使用者的id。那要如何控制使用者已經登入才能將商品加入購物車?
<?php
require_once "header.php";
session_start();
$account = "";
try {
require_once 'db.php';
$sql = "select * from product";
$result = mysqli_query($conn, $sql);
if($_SESSION && $_SESSION["account"]){
$account = $_SESSION["account"];
}
?>
<script>
cart = [];
function addToCart(pid){
//取得php變數
account = "<?=$account?>";
if (account == ""){
alert("請先登入");
return;
}
cart.push(pid);
document.getElementById("cart").innerText = "購物車內容:"+cart.join(",");
// alert("已加入購物車"+cart.join(","));
}
function showCart(){
window.location.href = "checkout.php?cart="+cart.join(",");
}
</script>
接下來,先預設每個商品的購買數量為1,並產生訂單及訂單明細。
這裡要提醒的部份是:當我們新增一筆訂單後,要取得訂單編號,才能在訂單明細中加上訂單編號。
<?php
session_start();
if (!$_SESSION || !$_SESSION["account"]){
header("Location: index.php");
}
if (!$_GET || !$_GET["cart"]){
header("Location: productQuery.php");
}
$account = $_SESSION["account"];
echo $_GET["cart"];
//將cart收到的資料轉換成陣列
$cart = explode(",", $_GET["cart"]);
//新增資料到sales_order
require_once 'db.php';
$sql = "insert into sales_order (user_account, order_date) values (?, now())";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, "s", $account);
mysqli_stmt_execute($stmt);
$sales_order_id = mysqli_insert_id($conn);
mysqli_stmt_close($stmt);
//新增資料到sales_order_detail
$sql = "insert into sales_order_detail (order_id, product_id, quantity) values (?, ?, 1)";
$stmt = mysqli_prepare($conn, $sql);
foreach($cart as $product_id){
mysqli_stmt_bind_param($stmt, "ii", $sales_order_id, $product_id);
mysqli_stmt_execute($stmt);
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
//回到index.php
header("Location: index.php");
?>
購物車也可以利用javascript的localstorage,好處是,不需要利用$_GET,傳遞cart的內容。缺點是,資料存在電腦裡,到另一台電腦就無法取得購物車的內容了。
現在很多的購物車其實都是存在資料庫裡,網路上範例很多,大家可以自行參考。