高級資料庫管理

學生拍賣系統資料庫

資料庫架構

albums

名稱 資料類型 空值 備註
id * int(10) A_I
user_id # int(10) 使用者ID
albumable_id int(10) ---
albumable_type varchar(255) ---
name varchar(255) 相簿名稱
description text 描述
cover_image varchar(255) 相簿封面
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `albums` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `albumable_id` int(10) unsigned NOT NULL,
  `albumable_type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `cover_image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `albums_user_id_foreign` (`user_id`),
  CONSTRAINT `albums_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

categories

名稱 資料類型 空值 備註
id * int(10) A_I
name varchar(255) 項目類別名稱
en_name varchar(255) 項目類別名稱(英)
type varchar(255) 項目類別分類
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `categories` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `en_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

comments

名稱 資料類型 空值 備註
id * int(10) A_I
user_id # int(10) 使用者ID
commentable_id int(10) ---
commentable_type varchar(255) ---
content COLLATE 留言內容
status int(11) 留言開放狀態
comment_parent int(11) ---
anonymous int(11) 匿名
deleted_at timestamp 刪除時間戳記
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `comments` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `commentable_id` int(10) unsigned NOT NULL,
  `commentable_type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `status` int(11) NOT NULL,
  `comment_parent` int(11) NOT NULL,
  `anonymous` int(11) NOT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `comments_user_id_foreign` (`user_id`),
  CONSTRAINT `comments_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=195 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
						

facebooks

名稱 資料類型 空值 備註
id * int(10) A_I
user_id # int(10) 使用者ID
facebook_id varchar(255) facebook帳號
name varchar(255) FB使用者名稱
email varchar(255) FB使用者信箱
avatar varchar(255) 頭像圖片
avatar_original varchar(255) 原始頭像圖片
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `facebooks` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `facebook_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `avatar` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `avatar_original` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `facebooks_user_id_foreign` (`user_id`),
  CONSTRAINT `facebooks_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

images

名稱 資料類型 空值 備註
id * int(10) A_I
album_id # int(10) 相簿ID
file_name varchar(255) 相簿名稱
file_size int(11) 檔案大小
file_mime varchar(255) 文件格式
file_path varchar(255) 檔案路徑
description varchar(255) 檔案描述
cover_img int(11) 檔案封面圖案
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `images` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `album_id` int(10) unsigned NOT NULL,
  `file_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `file_size` int(11) NOT NULL,
  `file_mime` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `file_path` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `cover_img` int(11) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `images_album_id_foreign` (`album_id`),
  CONSTRAINT `images_album_id_foreign` FOREIGN KEY (`album_id`) REFERENCES `albums` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
						

item_user

名稱 資料類型 空值 備註
id * int(10) A_I
user_id # int(10) 使用者ID
item_id # int(10) 項目ID
price int(11) 價格
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `item_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `price` int(11) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `item_user_user_id_foreign` (`user_id`),
  KEY `item_user_item_id_foreign` (`item_id`),
  CONSTRAINT `item_user_item_id_foreign` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`) ON DELETE CASCADE,
  CONSTRAINT `item_user_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=139 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

items

名稱 資料類型 空值 備註
id * int(10) A_I
name varchar(100) 項目名稱
price int(11) 價格
description text 描述
new tinyint(1) 新品
free tinyint(1) 免費
disabled int(11) 項目開放狀態
hitpoint int(11) 點擊數量
user_id # int(10) 使用者ID
category_id # int(10) 拍賣品分類ID
target int(11) 拍賣品對象
start_time timestamp 拍賣開始時間
end_time timestamp 拍賣結束時間
type int(11) 交易方法種類
repost int(11) 商品說明報告
notification tinyint(1) 訊息通知
deleted_at timestamp 刪除時間戳記
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `price` int(11) NOT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `new` tinyint(1) NOT NULL,
  `free` tinyint(1) NOT NULL,
  `disabled` int(11) NOT NULL,
  `hitpoint` int(11) NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `target` int(11) NOT NULL,
  `start_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `end_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `type` int(11) NOT NULL,
  `repost` int(11) NOT NULL,
  `notification` tinyint(1) NOT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `items_user_id_foreign` (`user_id`),
  KEY `items_category_id_foreign` (`category_id`),
  CONSTRAINT `items_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE,
  CONSTRAINT `items_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

majors

名稱 資料類型 空值 備註
id * int(10) A_I
name # varchar(255) 主修名稱
acronym varchar(255) 名稱英文縮寫
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `majors` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `acronym` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

reports

名稱 資料類型 空值 備註
id * int(10) A_I
user_id # int(10) 使用者ID
reportable_id int(10) 投訴ID
reportable_type varchar(255) 投訴分類
content text 投訴內容
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `reports` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `reportable_id` int(10) unsigned NOT NULL,
  `reportable_type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `reports_user_id_foreign` (`user_id`),
  CONSTRAINT `reports_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

users

名稱 資料類型 空值 備註
id * int(10) A_I
major_id int(10) 主修名稱ID
college_id # int(10) 學校名稱ID
username varchar(20) 使用者姓名
pseudonym varchar(255) 使用者簡稱
firstname varchar(10) 使用者姓氏
lastname varchar(10) 使用者名稱
email varchar(255) 使用者主要信箱
other_email varchar(255) 使用者信箱
password varchar(255) 登入密碼
birthday date 出生日期
gender int(11) 使用者性別
phone varchar(255) 使用者手機
avatar varchar(255) 使用者圖像
line_username varchar(255) ---
telegram_username varchar(255) ---
activation_code varchar(255) 繳活碼
actived int(11) 是否繳活
activated_at date 繳活時間
last_login date 最後登入時間
registed_ip varchar(255) 註冊時IP位置
login_ip varchar(255) 登入時IP位置
permission int(11) 權限
access_token varchar(255) ---
read_notification_at date ---
remember_token varchar(100) ---
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `major_id` int(10) unsigned NOT NULL DEFAULT '0',
  `college_id` int(10) unsigned NOT NULL DEFAULT '0',
  `username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `pseudonym` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `firstname` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `lastname` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `other_email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `birthday` date NOT NULL,
  `gender` int(11) NOT NULL,
  `phone` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `avatar` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `line_username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `telegram_username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `activation_code` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `actived` int(11) NOT NULL DEFAULT '0',
  `activated_at` date NOT NULL,
  `last_login` date NOT NULL,
  `registed_ip` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `login_ip` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `permission` int(11) NOT NULL,
  `access_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `read_notification_at` date NOT NULL,
  `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`),
  KEY `users_major_id_foreign` (`major_id`),
  KEY `users_college_id_foreign` (`college_id`),
  CONSTRAINT `users_college_id_foreign` FOREIGN KEY (`college_id`) REFERENCES `colleges` (`id`),
  CONSTRAINT `users_major_id_foreign` FOREIGN KEY (`major_id`) REFERENCES `majors` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
					

colleges

名稱 資料類型 空值 備註
id * int(10) A_I
name varchar(255) 學校名稱
acronym varchar(255) 學校簡寫
email varchar(255) 使用者信箱
description varchar(255) ---
address varchar(255) 學校地址
phone varchar(255) 學校電話
group_id varchar(255) ---
created_at timestamp 建立時間戳記
updated_at timestamp 更新時間戳記

CREATE TABLE `colleges` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `acronym` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `address` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `phone` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `group_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
						

多態數據關係

(Polymorphic Relationship)

以下情況你會如何設計資料表?

用戶可以對項目進行評論;

用戶可以對相簿進行評論;

用戶可以對圖片進行評論;

建立item_comments, album_comments 和image_comments三個資料表?

xxxable_id與xxxable_type兩個字段,前者用來存儲相關聯內容的外鍵鍵值,後者則用來存儲相關聯內容的類型名

Albums | Comments | Reports

軟刪除

(Soft Delete)

什麼是軟刪除?

是隱藏在資料庫中條目的能力,代替移除條目的一切痕跡。這意味著資料可在日後被用來檢索。另一種想法是歸檔資料。

Comments | Items

SQL Injection

SQL攻擊簡稱隱碼攻擊,是發生於應用程式之資料庫層的安全漏洞

User Table

id username password
1 ixiapeng df1f57
2 johnkwong 1353d2
3 normanlee 874095

login.php



$username = $_POST['username'];
$password = $_POST['password'];

$sql = "SELECT * FROM user WHERE username = '$username' and password = '$password'";
$result = mysqli_query($db,$sql);
if($result) {
	 session_register("username");
	 $_SESSION['login_user'] = $username;
	 header("location: welcome.php");
}else {
	 $error = "Your Login Name or Password is invalid";
}
						

Username: johnkwong

Password: ' 1 OR 1 = 1


SELECT * FROM user WHERE username = johnkwong and password = 1 OR 1 = 1
						

在Textbox輸入以上資料會使查詢成功。因為OR 1 = 1永遠是True

id username password
2 johnkwong 1353d2

還會更危險嗎?

使用Kali Linux OS 和SQLMAP工具滲透測試, 可以用來測試公司網路會被駭客駭入和滲透的程度

先輸入一些SQL找出網站弱點, 使網頁顯示SQL Error 頁。

因為網頁不是而GET方法傳遞資料, 而是POST方法, 沒有顯出Body 資料,所以比較煩, 我們只好用LiveHTTP header一直Replay提交一 些怪怪SQL語法和顯示header資訊。直到網頁顯示SQL Error 頁面。

從LiveHTTP header內Copy Error Page 的 URL和Cookies。再放到以上指令內, 去列出Server的資料庫。

打開目標網頁

看到資料庫是Mysql 5.0 Version 或相關資料。最近會列出資料庫。

列出資料庫table

列出資料庫columns

列出Column 的所以資料。如果拿到username & password 等資料。就可以 使用登入系統, 再進行資料修改/ 刪除動作。

如何解決?

使用MD5 Hash

MD5 Hash


INSERT INTO users (username,password) values ('johnkwong',md5('1353d2'));
						

User Table

id username password
1 ixiapeng 040620d34ce1ce5ad40d4ac2a972f6f7
2 johnkwong c5b597ddae90b6d05638ff85dbc89f61
3 normanlee 2001a2915e46bbb8b5404d7e816d28ca

在設計程式時, 考慮使用MD5 Hash對密碼進行加密。使用加密過的密碼沒法登入系統或進入步破壞。

Thank you!