這週的 hw1~hw3 是連續的作業,只要交一份就好,不用每一個都特地交一個。然後記得把你連線到資料庫的檔案(conn.php),加入.gitignore
,否則這檔案會被放到 GitHub 上,大家就知道資料庫的帳號密碼了。
另外,請你在留言板的最上方加註一行警語:「本站為練習用網站,因教學用途刻意忽略資安的實作,註冊時請勿使用任何真實的帳號或密碼」,加警語的目的是因為這週要做的網站極度不安全,很有可能被駭客拿到整個資料庫的資料,因此請切記在這網頁上不要輸入任何敏感資訊。
在課程中有提到上次寫的會員系統的缺陷之一,那就是密碼存明碼。密碼存明碼的風險就是一旦你的伺服器被入侵,資料庫被偷走的時候,使用者的密碼就外洩了。
你可能會問說:「所以,難道資料庫不能存密碼嗎?」
是的,我們要改存「另外一種形式」。
這是什麼意思呢?有一種東西叫做:Hash function,中文翻作雜湊函數,這個函數的重點就是它是單向的。你輸入 123 可以得到 202cb962ac59075b964b07152d234b70,但你沒辦法從 202cb962ac59075b964b07152d234b70 推出輸入是 123。
聽起來很神奇對吧?
所以我們的密碼就必須利用這種 hash function,在存入資料庫以前先轉變成另外一種形式。在驗證密碼的時候也是同理,我們不驗證密碼,而是驗證hash_function(password)
跟資料庫裡面所存的密碼是不是一致。
這樣一來,就算我們的資料庫整個被偷走,駭客們還是不知道使用者的密碼是什麼(或其實是說很難知道啦,要花很多時間)。
PHP 在 5.5 以上提供了兩個函式:password_hash
跟password_verify
,請你利用這兩個函式把之前會員註冊跟登入的頁面改寫,讓你的系統變得更安全一點。
在上一週的作業裡面,我們把會員的帳號存在 Cookie 裡面,藉此判斷會員是不是已經登入了,以及驗證身份。可是這樣子做其實會有問題產生,首先,先跟我唸一遍資安金句:
千萬不要相信來自 Client 端的資料
為什麼?因為只要是存在 Client 端的資料,都是可以被篡改的。假設有人把 Cookie 裡面的會員帳號改成:admin,那他就可以以管理員的身份登入了。
那要怎麼辦才好呢?
你可以回想你要去商業辦公大樓面試的時候,通常會要你在櫃檯換證。換了證之後,認證不認人,你的證是誰,你就是誰。在會員系統的實作上面,我們也可以參考這一個機制。
- 會員輸入帳號密碼,按下登入
- 若錯誤,返回錯誤訊息
- 若正確,亂數產生一個通行證 ID,並且在資料庫裡面記下通行證 ID 與會員 ID 的對應關係
- 把通行證 ID 設置到 Cookie
- 下次再發 Request 來,就會把通行證 ID 一起帶上來
- 檢查通行證 ID 是否有對應到的 ID,有的話就代表是那個人
我們引入了通行證的機制以後,就不用怕有人會竄改 Client 端的資料了,除非通行證被偷走,不然不可能用猜的把通行證 ID 猜出來。(所以你的通行證 ID 通常會長得很像亂碼,可以去查查 PHP 怎麼去產生亂數)
現在這個作業,就要你把會員系統的驗證換成上面這個通行證的機制,你會需要在資料庫新增一個 Table 來儲存通行證跟帳號的對應關係,可參考以下結構:
Table 名稱:users_certificate
欄位名稱 | 欄位型態 | 說明 |
---|---|---|
id | VARCHAR(32) | 通行證 id |
username | VARCHAR(16) | 帳號 |
(附註:這一題你絕對不會用到 $_SESSION 這個東西,如果你查到任何跟 $_SESSION 有關的東西請自動略過。)
在上次的作業中,只有顯示留言跟新增留言這兩個基本功能而已。而這次的作業,我們要再多加幾個功能,讓這個留言板變得更完整。
- 會員可以刪除自己的留言
- 會員可以編輯自己的留言
- 實作分頁系統,一頁只顯示二十筆資料,並且可以換到其他頁
- 請說明雜湊跟加密的差別在哪裡,為什麼密碼要雜湊過後才存入資料庫
- 請舉出三種不同的雜湊函數
- 請去查什麼是 Session,以及 Session 跟 Cookie 的差別
include
、require
、include_once
、require_once
的差別
請將答案寫在 hw4.md。
新增一個「管理員」的功能以及後台。
幫每個 user 都加上一個新的欄位代表身份,身份有兩種:normal 跟 admin。
新增一個管理員專屬的後台,身份要是 admin 才看得到,進去之後可以看到所有的文章,並且有權限編輯與刪除任意一篇文章。
承上,再新增另一種新的身份叫做 super admin。
新增一個權限管理的頁面,只有 super admin 看得見,而 super admin 可以看到所有會員的資料,並且把任意使用者的身份改成 admin。