- 會員的註冊需要注意的項目:為了擔心被攻擊,你的註冊一定需要考慮到帳號的英數限制
- 因為常有 SQL injection 的攻擊,因此建議,你的『帳號』應該要加入不少的限制比較妥當!
舉例來說,例如只能是英文與數字,最多還有底線或減號以及小數點,其他的就予以限制這樣比較妥當。
- 密碼欄位當然一定要編碼加密,我們在本案例中,選擇使用簡單的 sha256 (hash('sha256',$pw)) 來處理密碼欄位!
越嚴格的密碼所佔的表單欄位寬度要更長!
- 最好有防呆的機制,例如不能有相同的帳號名稱、不能不輸入密碼、限制密碼最小長度等等,都是一些基本的限制與考量。
- 最好能夠讓管理員來放行使用者的註冊!不要一經註冊就能使用 (當然,也可以加上許多的註冊機器人防治手法!)
- 開始建立註冊的基本頁面 (註冊所需要的資料通通列在上面喔!)
$ vim register.php
<?php
include ('include/config.php');
?>
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
</head>
<body>
<form>
<table>
<tr>
<td>登入帳號:</td>
<td><input type="text" name="login_name" required="required" /></td>
<td>帳號只能是英文、數字、底線、減號與小數點,其餘字元均不接受</td>
</tr>
<tr>
<td>登入密碼:</td>
<td><input type="password" name="login_pass11" required="required" /></td>
<td>至少 5 個位數以上的密碼長度</td>
</tr>
<tr>
<td>確認密碼:</td>
<td><input type="password" name="login_pass12" required="required" /></td>
<td>再輸入一次密碼,確認沒有打錯字</td>
</tr>
<tr>
<td>真實姓名:</td>
<td><input type="text" name="realname" required="required" /></td>
<td>填寫註冊者的姓名</td>
</tr>
<tr>
<td>電子郵件:</td>
<td><input type="email" name="u_email" /></td>
<td>請填慣用的電子郵件</td>
</tr>
<tr>
<td>生日:</td>
<td><input type="date" name="u_bday" required="required" /></td>
<td>請務必使用 YYYY-MM-DD 的格式,如 1990-01-20</td>
</tr>
<tr>
<td>性別:</td>
<td><select name="u_sex">
<option value="0">女性</option>
<option value="1">男性</option>
</select></td>
<td>選擇性別</td>
</tr>
<tr>
<td colspan="3" style="text-align:center; ">
<input type="hidden" name="action" value="reg" />
<input type="submit" value="送出註冊" />
</td>
</tr>
</table>
</form>
</body>
</html>
- 開始設計防呆的樣式!注意到許多 javascript 的應用喔!尤其是正規表示法的部份:
$ vim register.php
<?php
include ('include/config.php');
?>
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
</head>
<body>
<form id="regform" onsubmit="return checkinput()" >
<table>
<tr>
<td>登入帳號:</td>
<td><input type="text" name="login_name" required="required" id='login_name' /></td>
<td>帳號只能是英文、數字、底線、減號與小數點,其餘字元均不接受</td>
</tr>
<tr>
<td>登入密碼:</td>
<td><input type="password" name="login_pass1" required="required" id='login_pass1' /></td>
<td>至少 5 個位數以上的密碼長度</td>
</tr>
<tr>
<td>確認密碼:</td>
<td><input type="password" name="login_pass2" required="required" id='login_pass2' /></td>
<td>再輸入一次密碼,確認沒有打錯字</td>
</tr>
<tr>
<td>真實姓名:</td>
<td><input type="text" name="realname" required="required" /></td>
<td>填寫註冊者的姓名</td>
</tr>
<tr>
<td>電子郵件:</td>
<td><input type="email" name="u_email" /></td>
<td>請填慣用的電子郵件</td>
</tr>
<tr>
<td>生日:</td>
<td><input type="date" name="u_bday" required="required" id='bday' /></td>
<td>請務必使用 YYYY-MM-DD 的格式,如 1990-01-20</td>
</tr>
<tr>
<td>性別:</td>
<td><select name="u_sex">
<option value="0">女性</option>
<option value="1">男性</option>
</select></td>
<td>選擇性別</td>
</tr>
<tr>
<td colspan="3" style="text-align:center; ">
<input type="hidden" name="action" value="reg" />
<input type="submit" value="送出註冊" />
</td>
</tr>
</table>
</form>
<script>
function checkinput() {
// 檢查登入帳號是否有特殊字元
var re = /[^a-zA-Z0-9.-_]/;
var okname = re.exec ( document.getElementById("login_name").value);
if ( okname ) {
window.alert ( "指允許英文、數字、底線、小數點與減號" );
document.getElementById("login_name").focus();
return false;
}
// 開始檢查密碼長度是否正確?
var pw1 = document.getElementById("login_pass1");
if ( pw1.value.length < 5 ) {
window.alert ( "密碼長度必須要大於 5 個字元以上" );
document.getElementById("login_pass1").focus();
return false;
}
// 看看兩次密碼是否相同?
var pw2 = document.getElementById("login_pass2");
if ( pw1.value != pw2.value ) {
window.alert ( "兩次密碼並不相同!" );
document.getElementById("login_pass1").focus();
return false;
}
// 檢查生日的格式正確與否
re = /^[0-9]{4}[./-][0-9]{2}[./-][0-9]{2}$/;
var okday = re.exec ( document.getElementById("bday").value);
if ( ! okday ) {
window.alert ( "日期格式為 2011-11-11" );
document.getElementById("bday").focus();
return false;
}
}
</script>
</body>
</html>
- 若一切檢查都正確,當然就是要開始上傳了。上傳時,請注意到資料還是得要加入 SQL 語法的檢驗喔!
$ vim register.php
<?php
include ('include/config.php');
if ( isset ( $_REQUEST['action'] ) ) {
if ( $_REQUEST['action'] == 'reg' ) {
// 先取得所需要的變數資料
$login_name = $_REQUEST['login_name'];
$login_pass1 = $_REQUEST['login_pass1'];
$login_pass2 = $_REQUEST['login_pass2'];
$realname = $_REQUEST['realname'];
$u_email = $_REQUEST['u_email'];
$u_bday = $_REQUEST['u_bday'];
$u_sex = $_REQUEST['u_sex'];
// 檢查登入者的帳號長度
if ( strlen($login_name) < 5 ) {
echo"<script>alert('登入帳號字元不足 5 個字元');history.go(-1);</script>";
die;
}
if ( $login_pass1 != $login_pass2 ) {
echo"<script>alert('兩次密碼輸入不相同');history.go(-1);</script>";
die;
}
$login_pass = hash ('sha256', $login_pass1);
$sql = "insert into userinfo (login_name,login_pass,realname,u_email, u_bday,u_sex) values (" .
"'$login_name', " .
"'$login_pass', " .
"'$realname', " .
"'$u_email', " .
"'$u_bday', " .
"'$u_sex' ) " ;
$result = mysql_query ($sql, $db_link );
if ( $result ) {
header("Location: listuser.php");
} else {
echo"<script>alert('無法註冊!');history.go(-1);</script>";
die;
}
}
}
?>
<!doctype html>
後續的資料不變
- 雖然寫入了資料庫,但是並沒有防呆!所以,這時開始來防呆一下!
$ vim register.php
//只要新增這一塊,請放在『 $login_pass = hash ('sha256', $login_pass1); 』這一行的前面就可以了!
// 先查一下有沒有這個帳號存在了?
$sql = "select * from userinfo where login_name = '$login_name'";
$result = mysql_query ($sql, $db_link );
$db_line = mysql_num_rows($result);
if ( $db_line >= 1 ) {
echo "<script>alert('這個帳號已經存在了!請使用其他帳號註冊');history.go(-1);</script>";
die;
}
- 再來開始處理註冊機器人的問題。這裡我們使用最單純的自己設定一個圖檔來處理,不過 PHP 繪圖,需要自己處理相關函式庫,
同時得要安裝 php-gd 模組才行!
# yum install php-gd (這裡要用 root 的權限)
# systemctl restart httpd (這裡要用 root 的權限)
$ mkdir ~/www/images (恢復 student 的權限)
$ chmod 777 ~/www/images
$ vim include/captcha.php
<?php
// 開始驗證碼 https://gnehcic.azurewebsites.net/php建立圖形驗證碼/
$CaptchaString = ""; //驗證碼文字
$CaptchaLength = 5; //驗證碼長度
//產生數字驗證碼
for($i=0; $i < $CaptchaLength; $i++)
$CaptchaString = $CaptchaString.rand(0,9);
$_SESSION['CAPTCHA'] = $CaptchaString; //驗證碼存入SESSION內
$CaptchaWidth = 70; //驗證碼影像寬度
$CaptchaHeight = 20; //驗證碼影像高度
//建立影像
$Captcha = ImageCreate($CaptchaWidth, $CaptchaHeight);
//設定背景顏色,範例是紅色
$BackgroundColor = ImageColorAllocate($Captcha, 255, 0, 0);
//設定文字顏色,範例是黑色
$FontColor = ImageColorAllocate($Captcha, 0, 0, 0);
//影像填滿背景顏色
ImageFill($Captcha, 0, 0, $BackgroundColor);
//影像畫上驗證碼
ImageString($Captcha, 6, 14, 3, $_SESSION['CAPTCHA'] , $FontColor);
//imagettftext($Captcha, 20, 0, 0, 0, $FontColor, 'Times', $_SESSION['CAPTCHA'] );
//隨機畫上200個點,做為雜訊用
for($i = 0; $i < 100; $i++) {
Imagesetpixel($Captcha, rand() % $CaptchaWidth , rand() % $CaptchaHeight , $FontColor);
}
//輸出驗證碼影像
$filename = sprintf( "./images/check.png", time());
ImagePNG($Captcha, $filename);
ImageDestroy($Captcha);
?>
$ vim register.php
session_start();
include ('include/config.php');
if ( isset ( $_REQUEST['action'] ) ) {
....
} else {
include ('include/captcha.php');
}
// 之後在 submit 的表單內,增加底下這個資料
<td colspan="3" style="text-align:center; ">
<img src="images/check.png" /><br />
<input type="text" name="checking" /><br />
<input type="hidden" name="action" value="reg" />
<input type="submit" value="送出註冊" />
</td>
- 再來就得要注意註冊時,得要先檢查這個驗證碼!驗證碼的數字已經記載在前一次填寫資料的 $_SESSION['CAPTCHA'] 這個 session 內,
所以,首先就得要處理這個項目的資料才行!這個項目如果不對,就直接丟回去前一頁囉!因此這樣做即可:
$ vim register.php
session_start();
include ('include/config.php');
if ( isset ( $_REQUEST['action'] ) ) {
if ( $_REQUEST['action'] == 'reg' ) {
// 先確認是否取得正確的註冊驗證碼
$checking = $_REQUEST['checking'];
if ( $_SESSION['CAPTCHA'] != $checking ) {
echo "<script>alert('驗證碼設定錯誤,請重新填寫註冊資料');history.go(-1);</script>";
die;
}
// 先取得所需要的變數資料
....