會員註冊
會員註冊首頁載入時
1. [安全] 網域檢查
if ($_SERVER['HTTP_HOST'] != 'domain'){
exit('不允許的網域。');
}
2. 登入 Session 檢查 (若為登入狀態,強制移動至首頁)
if($_SESSION['session_id']){
header('Location: '.$url);
exit;
}
3. SSL 相關處理
if(!isset($_SERVER["HTTPS"])){
$url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header('Location: '.$url);
}
4. i-Pin 認證,本人認證(手機)
此部分使用 form 標籤建立相關請求,並處理回傳值。
5. 同意使用條款 </span>
使用 JavaScript 確認該核取方塊是否已勾選後再進行下一步。
登入
1. 傳送登入資料
:使用表單標籤傳送帳號、密碼。
2. [安全] 網域檢查
if ($_SERVER['HTTP_HOST'] != 'domain'){
exit('不允許的網域。');
}
3. 防止外部產生的表單資料傳送 </span>
function referer(){
$http_referer = str_replace('http://','',$_SERVER['HTTP_REFERER']);
$http_referer = str_replace('https://','',$http_referer);
$referer = explode('/',$http_referer);
if ($referer[0] <> $_SERVER['HTTP_HOST']) {
//使用警告視窗指令碼處理較方便 echo '....';
exit;
}
}
4. 確認傳入的值
$user_id = trim( $_POST['userid'] );
$user_id= $mysqli_accountdb_s1->real_escape_string( $userid );// 防止 SQL Injection
$pw = trim( $_POST['password'] );
$backurl = trim( $_POST['backurl'] );
if (!$backurl) {
$backurl = trim( $_GET['backurl'] ); // 登入完成後返回的 URL
}
$backurl = xss_replace($backurl); // 透過防止跨站指令碼(XSS)函式處理字串
if (!$backurl) {
$backurl = '設定主網址'; // 若無返回 URL,則設定為主網址
}
5.雜湊處理
$encode_pw = sha1($pw);
6. 使用 Session 處理連續登入延遲
if($_SESSION['ss_logintime'] != '') {
$chk_time = mktime(date("H"),date("i"),date("s")-10,date("m"),date("d"),date("Y"));
if ($chk_time < strtotime($_SESSION['ss_logintime'])) {
$msg = "正在登入中,請稍候。";
msg($msg); // 顯示通知
ob_flush();
flush();
sleep(2);
}
}
$_SESSION['ss_logintime'] = date('Y-m-d H:i:s');
7. IP 檢查
利用 Cookie 進行 IP 檢查 + 限制登入次數 (10次以下) > 限制 10 分鐘 (將登入時間寫入 Cookie 處理)
8. 登入機器人檢查
防止利用暴力破解法進行駭客攻擊。
9. 實際使用者檢查
確認使用者是否存在、是否為已註冊使用者、密碼是否正確。此部分可透過 Query 檢查,或在 PHP 內部檢查。
10. 海外 IP 封鎖檢查
透過封鎖海外 IP 防止繞道駭客攻擊。
11. 登入失敗次數累計 5 次以上禁止登入 > 引導至忘記密碼
若登入失敗次數超過 5 次,則重新導向至忘記密碼頁面。
12. 開始登入
建立 Session。
13. 更新使用者資訊與最終登入資訊
session_id、登入失敗次數、登入日期、登入 IP。
14. 新增登入紀錄
在登入歷史資料表中寫入登入紀錄。
15. 簡易會員、Facebook 會員檢查
強制移動至轉換為正式會員的選單。
16. 檢查密碼變更
確認密碼是否已超過 90 天未變更。
MySQL
1. 即使 Insert 發生錯誤,auto_increment 值仍會增加。
實際上,使用 MySQLi 執行 insert 查詢後,即使因為 duplicate 等錯誤導致紀錄未寫入,該 auto_increment 鍵值仍會 +1 增加。
在下一篇文章中稱此為 MySQL 臭蟲。
(http://desmart.com/blog/be-careful-with-mysqls-auto-increment-how-we-ended-up-losing-data)
QA
1. 
若螢幕上顯示以下代碼,且未顯示預期的 echo 值。 
這是「編碼問題」。
解決方法是使用 Notepad++ 將該檔案的編碼轉換為 UTF-8 (無 BOM) 即可解決。
2. 若要在 HTML 檔案中執行 PHP 程式碼
(1) 在 httpd.conf 檔案內輸入以下內容:
AddHandler application/x-httpd-php .html
(2) 在 .htaccess 檔案內輸入以下內容:
AddType application/x-httpd-php .html
global 是什麼?
global 是當函數中使用的變數名稱與全域變數相同時,用來存取全域變數的語法。
在 iOS 的程式碼中,可以想成類似 self.變數名稱 的感覺。
參考事項
[SERVER]
$_SERVER['REQUEST_URI'] = 當前頁面網址中扣除網域的部分 = index.phpuser=&name=
$_SERVER['PHP_SELF'] = 當前頁面網址中扣除網域與傳遞參數的部分 = index.php
[required or required_once, include or include_once]
原先使用 required、include,後來改用 required_once、include_once。
使用這些 API 的原因是為了避免重複定義函數。
不過,據說這些 API 會拖慢速度。
因此,據說採取以下方式較好:
if (!defined('MyIncludeName')) {
require('MyIncludeName');
define('MyIncludeName', 1);
}
以下是測試比較結果:
php hhvm
if
defined
0.18587779998779
0.046600103378296
require_once
1.2219581604004
3.2908599376678
[額外建議 (TIP)]
echo 比 print 快。
包覆字串時,單引號(') 比雙引號(") 快。
原因是 PHP 會在雙引號中尋找變數,而在單引號中則不會。
若字串中沒有變數,請使用單引號。
請使用預先計算好的值。在 for 迴圈中設定最大值時,請不要將計算放在迴圈內:
請在 for 迴圈開始前先使用 $max = count($array)
for($x=0;$x<count($array);$x++) ==> for($x=0;$x<$max;$x++)
為了釋放記憶體, 大型陣列必須使用 unset 或 null 處理。
str_replace 比 preg_replace 快。 str_replace 通常是首選,但 strstr 在某些大型字串處理時有時更快。在 str_replace 中使用陣列通常比使用多次 str_replace 更快。
else if 語法比 switch 快。
使用完後請關閉資料庫連線。
$row['id'] 比 $row[id] 快 7 倍。 如果不使用單引號,系統必須猜測你指的是什麼索引。
宣告 PHP 時請使用 <?php ... ?>,其他樣式皆為不規範。
請使用嚴格的程式碼,避免隱藏 notice、warning 和 error。這樣能產生更乾淨的程式碼並降低負載。 考慮隨時開啟 error_reporting(E_ALL)。
使用 header('location:'.$url); 時,請記得同時使用 exit。 即使位置已切換,指令碼仍會繼續執行。
變數請先初始化再使用,否則會非常慢。
用來隱藏錯誤的 @ 符號非常慢。
執行單純 SELECT 功能時建議使用 GET 方法,而 UPDATE 功能則建議使用 POST。
因為 GET 會被快取,速度相對較快。(POST 不會被快取)
PHP 5.2.9 不支援將 array() 寫成 '[ ]',請注意。
若現有原始碼使用 '[ ]' 來定義陣列,在 5.2.9 版本中必須改為 array()。
Do not use preg_match()
if you only want to check if one string is contained in another string.
Use strpos() or strstr() instead as they will be faster.
</span>