PHP

Home

PHP Tutorial
Knowledge Developer Database Internet Resource
ระบบการรับรองของ PHP และ MySQL
1. การระบุผู้ใช้
2. การรับรองพื้นฐาน
 
การสร้างโปรแกรมประยุกต์เว็บ
1. Cookie และ Session
2. ระบบการรับรองของ PHP และ MySQL
3. XML และ XHTML
4. PEAR
 
PHP
PHP เบื้องต้น
การสร้างโปรแกรมประยุกต์เว็บ
PHP ระดับสูง
 
Internet
PHP
SSI
HTML
AJAX
 
การสร้างโปรแกรมประยุกต์เว็บ > ระบบการรับรองของ PHP และ MySQL

การระบุผู้ใช้

เว็บเป็นตัวกลางปิดบังชื่อ แต่สามารถรู้ว่าใครเข้ามาถึงเว็บ

การติดต่อผ่านอินเตอร์เน็ตเป็นการ "สนทนา" ระหว่างคอมพิวเตอร์ผ่าน IP address ซึ่งระบบที่เป็นอยู่ไม่ใช่ identifier ถาวร ในขณะที่ แม่ข่ายสามารถค้นพบข้อมูลจำนวนมากเกี่ยวกับคอมพิวเตอร์และเครือข่ายที่เชื่อมต่อ

โชคดีสำหรับผู้ใช้เว็บ ไม่มีสารสนเทศที่ browser ของเขาต้องระบุตัวเอง ถ้าต้องการทราบถึงชื่อหรือรายละเอียดของผู้เยี่ยมชม จึงต้องมีการถาม

ควบคุมการเข้าถึง

การควบคุมการเข้าถึงอย่างง่ายใช้ได้ไม่ยาก ตัวอย่างชุดนี้ประกอบด้วยฟอร์ม HTML สำหรับการเข้าสู่ระบบ สคริปต์ประมวลผลที่จะพิจารณาว่าชื่อผู้ใช้และรหัสผ่านถูกต้องหรือไม่ ด้วยการเรียกไฟล์ ที่เก็บชุดคำสั่งสำหรับการประมวลผลการเข้าสู่ระบบ ถ้าถูกต้องจะไปยังเพจต้อนรับ กรณีอื่นส่งกลับไปยังฟอร์ม HTML พร้อมข่าวสารความผิดพลาดและให้ป้อนชื่อและรหัสผ่านให้ ภาพ 2.2.1 แสดงหน้าเข้าสู่ระบบ


ภาพ 2.2.1 หน้าจอป้อนชื่อและรหัสผ่าน

ถ้าข้อมูลนำเข้าไม่ถูกต้อง สคริปต์ประมวลผลจะส่งกลับมาหน้านี้ใหม่พร้อมข่าวสารความผิดพลาดตามภาพ 2.2.2


ภาพที่ 2.2.2 แสดงข่าวสารความผิดพลาดจากการเข้าสู่ระบบไม่ถูกต้อง

ถ้าชื่อและรหัสผ่าน สคริปต์ประมวลผลจะส่งไปหน้าต้อนรับตามภาพ 2.2.3


ภาพ 2.2.3 หน้าต้อนรับ ถ้าผ่านการประมวลผล


ภาพ 2.2.4 แสดงความผิดพลาดจากการเข้าสู่หน้าต้อนรับโดยตรง

เพจแรก basic_login.php ตามภาพที่ 2.2.1 และ 2.2.2 อยู่ในรายการคำสั่ง 2.2.1  ที่คุณลักษณะ action เป็น basic_process.php และอยู่ในรายการคำสั่ง 2.2.2 สำหรับเพจต้อนรับอยู่ในรายการคำสั่ง 2.2.3

ในสคริปต์ basic_process.php รวมไฟล์ basic_manager.inc สำหรับประมวลผลการเข้าสู่ระบบ ด้วย class UserManager ได้ แสดงในรายการคำสั่ง 2.2.1

รายการคำสั่ง 2.2.1 สคริปต์ basic_login.html

 

<h1>Widebase</h1>
<form action="basic_process.php" method="post">
<table width="300" border="0">
<tr>
<td width="75">ชื่อ</td>
<td><input name="username" type="text" size="30" maxlength="50"></td>
</tr>
<tr>
<td>รหัสผ่าน</td>
<td><input name="password" type="password" size="30" maxlength="50"></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input name="Login" type="submit" id="Login" value="Login"></td>
</tr>
</table>
</form>

รายการคำสั่ง 2.2.2 สคริปต์ basic_process.php

 

<?php

require_once('basic_manager.inc');

// 1. เริ่มต้น session()
session_start();
$_SESSION['valid'] = TRUE;
$_SESSION['msg'] = "prepare login";

// 2. ตรวจสอบการนำเข้า
if (!isset($_POST['username']) || $_POST['username'] == ''
|| !isset($_POST['password']) || $_POST['password'] == '')
{

$islogin[1] = "ไม่ได้ป้อนชื่อหรือรหัสผ่าน";
$islogin[0] = FALSE;

}
else
{

$user_name = $_POST['username'];
$user_pass = $_POST['password'];
$islogin[0] = TRUE;

}

// 3.  เรียก User Manager ประมวลผลการนำเข้า
if ($islogin[0] == TRUE)
{

$usermgr = new UserManager();
$islogin = $usermgr->processLogin($user_name, $user_pass);

}

// 4. ส่งต่อเพจ ถ้าสำเร็จไป basic_welcome.php  ถ้าล้มเหลวกลับไป basic_login.php
$_SESSION['valid'] = $islogin[0];
$_SESSION['msg'] = $islogin[1];

if ($islogin[0] == FALSE)
    header("Location:basic_login.php");
else
    header("Location:basic_welcome.php");

?>

รายการคำสั่ง 2.2.3 สคริปต์ basic_welcome.php

 

<?php
session_start();

if (!isset($_SESSION) )
{

echo "ท่านไม่ได้เข้าสู่ระบบ โปรดกลับไปหน้าเข้าสู่ระบบใหม่<br/>";
echo "<a href='basic_login.html'><font color=blue>เข้าสู่ระบบ</font></a>";

}
else if($_SESSION['valid'] == TRUE)
{

echo "<h1>ยินดีต้อนรับ</h1>";
echo "ท่านได้เข้าสู่ระบบเรียบร้อย";

}
else
{

echo "การเข้าสู่ระบบไม่ถูกต้อง โปรดกลับไปหน้าเข้าสู่ระบบใหม่<br/>";
echo "<a href='basic_login.html'><font color=blue>เข้าสู่ระบบ</font></a>"; 

}


?>

รายการคำสั่ง 2.2.4 สคริปต์ basic_manager.inc

 

<?php
define('USERNAME', 'myuser');
define('PASSWORD', 'password');

class UserManager
{

public function __construct()
{

// no code

}

public function processLogin($in_user_name, $in_user_passwd)
{

$valid = array();
// 1. ตรวจสอบอากิวเมนต์
if ($in_user_name == '' || $in_user_passwd == '')
{

$valid[1] = "เรียกฟังก์ชันด้วยพารามิเตอร์ไม่ถูกต้อง<br/>";
$valid[0] = FALSE;
exit;

}
// 2. ตรวจสอบชื่อและรหัสผ่าน
$valid = $this->confirmLogin($in_user_name, $in_user_passwd);
return $valid;

}

private function confirmLogin($in_uname, $in_upasswd)
{

// ชื่อเป็นตัวพิมพ์มีผล                   
$in_user_name = strtolower($in_uname);
$in_user_passwd = strtolower($in_upasswd);

$valid = array();
if ($in_user_name == USERNAME &&  $in_user_passwd == PASSWORD)
{

$valid[0] = TRUE;

}
else
{

$valid[0] = FALSE;
$valid[1] = "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง<br/>";

}

return $valid;

}

}
?>

ชุดคำสั่งนี้ จะให้กลไกรับรองอย่างง่ายเพื่อยอมให้รับรองผู้ใช้เพื่อดูเพจ แต่มีบางปัญหาสำคัญ สคริปต์นี้

  1. มี 1 ผู้ใช้และรหัสผ่าน เป็นคำสั่งตายตัวในสคริปต์
  2. เก็บรหัสผ่านเป็นข้อความปกติ
  3. ส่งผ่านรหัสผ่านเป็นข้อความปกติ

ประเด็นเหล่านี้สามารถแก้ไขได้เพิ่มระดับการเขียนคำสั่ง

การเก็บรหัสผ่าน

มีหลายที่สำหรับการเก็บชื่อผู้ใช้และรหัสผ่านที่ดีกว่าภายในสคริปต์ ภายในสคริปต์มีความลำบากในการปรับปรุงข้อมูล อาจจะเป็นไปได้แต่มีความคิดที่ไม่ดี ในการเขียนสคริปต์ให้ปรับปรุงตัวเอง หมายความว่าต้องมีบนแม่ข่ายซึ่งประมวลผลบนแม่ข่าย แต่เขียนหรือปรับปรุงโดยอีกสคริปต์ การเก็บข้อมูลในอีกไฟล์บนแม่ข่ายจะช่วยให้เขียนโปรแกรมเพื่อการเพิ่มหรือลบผู้ใช้  และแก้ไขรหัสผ่านได้ง่าย

ภายในสคริปต์หรือไฟล์ข้อมูลอีกไฟล์ มีข้อจำกัดด้านจำนวนของผู้ใช้โดยปราศจากผลกระทบความเร็วของสคริปต์ ถ้ากำลังพิจารณาการจัดเก็บและค้นหารายการจำนวนมากในไฟล์ควรพิจารณาการใช้ฐานข้อมูลแทน ถ้าต้องการเก็บและค้นหามากกว่า 100 รายการ ควรเก็บในฐานข้อมูลแทนที่ไฟล์ข้อความ

การใช้ฐานข้อมูลเพื่อเก็บชื่อและรหัสผ่านไม่ทำให้สคริปต์ซับซ้อนขึ้น แต่ยอมให้รับรองผู้ใช้หลายรายอย่างรวดเร็ว สิ่งนี้ยอมให้เขียนสคริปต์เพื่อเพิ่มผู้ใช้ใหม่ ลบผู้ใช้และยอมให้ผู้ใช้เปลี่ยนรหัสผ่านของตัวเอง

การปรับปรุงเป็นแก้ไขใน class UserManager ให้ทำให้กับฐานข้อมูล และเพิ่มไฟล์รวมที่เก็บสารสนเทศการเชื่อมต่อกับฐานข้อมูล สำหรับคำสั่งในสคริปต์อื่นไม่มีการเปลี่ยนแปลง

การเข้ารหัส

ถ้าไม่เก็บข้อมูลในฐานข้อมูลหรือไฟล์มีความเสี่ยงที่ไม่จำเป็นในเก็บรหัสข้อความปกติ อัลกอริทึมแฮชทางเดียว  สามารถให้ความปลอดภัยมากขึ้นเล็กน้อยด้วยความพยายามเพิ่มเล็กน้อย

ฟังก์ชัน crypt () ของ PHP เป็นฟังก์ชันแฮชเข้ารหัสทางเดียวไวยากรณ์ของฟังก์ชันนี้คือ
string crypt (string str [,string salt])

string str ส่งออกข้อความรหัส pseudo เป็น "pauONM/HSu9pM" ข้อความนี้ไม่สามารถได้รับถอดรหัสและส่งออกกลับเป็น "pass" โดยผู้ส่งออก คุณสมบัตินี้ทำให้ crypt () มีประโยชน์คือ ผลลัพธ์สิ้นสุด ถ้าให้ข้อความ salt เดียวกัน เช่น ‘xyz’ ฟังก์ชัน crypt () จะส่งออกผลลัพธ์เดียวกันทุกครั้งที่เรียกใช้ ตัวอย่าง
if (crypt($password, 'xyz') == "pauONM/HSu9pM");

นอกจากนี้สามารถใช้ฟังก์ชัน md5()

ถ้าใช้ฐานข้อมูล MYSQL เพื่อเก็บข้อมูลเข้ารหัส สามารถใช้ฟังก์ชัน crypt () หรือ md5() ของ PHP หรือ ฟังก์ชัน PASSWORD () ของ MySQL ฟังก์ชันเหล่านี้สร้างผลลัพธ์ไม่เหมือนกันแต่ให้บริการวัตถุประสงค์เดียวกันทั้ง crypt () และ PASSWORD () ใช้ข้อความและประยุกต์อัลกอริทึมแฮชย้อนกลับไม่ได้ (Non – Reversible Hash Algorithm)

การใช้ PASSWORD () สามารถเขียนประโยคคำสั่งคิวรี่

SELECT count (*) FROM users
WHERE name = '$name' AND pass = PASSWORD('$password')

คิวรี่นี้จะนับจำนวนแถวในตารางข้อมูล users ที่มีค่าตาม WHERE Clause โดยฟังก์ชัน PASSWORD () ที่ประยุกต์กับ $password สมมติว่าบังคับให้มีชื่อผู้ใช้ไม่ซ้ำ ผลลัพธ์ของคิวรี่นี้จะเป็น 0 หรือ 1

การป้องกันหลายเพจ

การสร้างสคริปต์ป้องกันมากกว่า 1 เพจ ยากขึ้นเล็กน้อย เนื่องจาก HTTP ไม่มีสถานะคือไม่มีการเชื่อมโยงหรือเกี่ยวข้องกันอย่างอัตโนมัติระหว่างคำขอต่อเนื่องจากบุคคลเดียวกัน สิ่งนี้ทำให้ยากกับการส่งผ่านข้อมูล เช่น สารสนเทศการรับรองว่าผู้ใช้ได้เข้ามาข้ามเพจ

วิธีการง่ายที่สุดในการป้องกันหลายเพจคือ ใช้กลไกควบคุมการเข้าถึงที่ให้โดยแม่ข่ายเว็บที่จะดูต่อไป

ในการสร้างการทำงานขึ้นเอง สามารถรวมส่วนของสคริปต์ตามรายการคำสั่ง 2.2.1 ในทุกเพจ ที่ต้องการป้องกัน การใช้ auto_prepend_file และ auto_append_file ทำให้สามารถเติมหน้าและต่อท้ายคำสั่งที่ต้องการกับทุกไฟล์ ในไดเรคทอรีเฉพาะ คำสั่งนี้ได้รับอธิบายแล้วในบทที่ 6 "คำสั่งใช้ใหม่และฟังก์ชัน"

ถ้าใช้วิธีการนี้จะไม่มีความต้องการให้ผู้เยี่ยมชมป้อนชื่อและรหัสผ่านสำหรับทุกเพจที่ต้องการดู

ในการเพิ่มรายละเอียดในการเข้าทุก  hyperlink บนเพจ ผู้ใช้อาจจะมี space หรือตัวอักษรอื่นที่ไม่ได้รับอนุญาตใน URL ควรใช้ฟังก์ชัน urlencode () เพื่อเข้ารหัสตัวอักษรเหล่านี้อย่างปลอดภัย

 


  

สงวนลิขสิทธิ์ (C) widebase / Julaphak