php การตรวจสอบสิทธิ์ที่ไม่สะทกสะท้าน HTTP การติดตั้งการป้องกันบนเพจโดยใช้ MySQL และ PHP แอปพลิเคชัน. แหล่งที่มาของสคริปต์
หากต้องการส่งข้อความ "ต้องมีการรับรองความถูกต้อง" ไปยังเบราว์เซอร์ไคลเอ็นต์ ซึ่งจะทำให้กล่องโต้ตอบปรากฏขึ้นเพื่อป้อนชื่อผู้ใช้และรหัสผ่าน หลังจากที่ลูกค้าป้อนชื่อและรหัสผ่านแล้ว สคริปต์จะถูกเรียกอีกครั้ง แต่มีตัวแปรที่กำหนดไว้ล่วงหน้า PHP_AUTH_USER, PHP_AUTH_PW และ AUTH_TYPE ซึ่งมีชื่อผู้ใช้ รหัสผ่าน และประเภทการตรวจสอบสิทธิ์ตามลำดับ ตัวแปรเหล่านี้สามารถพบได้ในอาร์เรย์ $_SERVER และ $HTTP_SERVER_VARS ปัจจุบันรองรับเฉพาะการตรวจสอบสิทธิ์แบบ "พื้นฐาน" เท่านั้น คุณยังสามารถอ่านคำอธิบายโดยละเอียดเพิ่มเติมของฟังก์ชันได้ ส่วนหัว() .
ตัวอย่างของส่วนของสคริปต์ที่บังคับให้ไคลเอนต์เข้าสู่ระบบเพื่อดูเพจ:
ตัวอย่างการรับรองความถูกต้อง HTTP
ถ้า (!isset($_SERVER [ "PHP_AUTH_USER" ])) ( สวัสดี ($_SERVER["PHP_AUTH_USER"]) คุณได้ป้อนรหัสผ่านของคุณ ($_SERVER["PHP_AUTH_PW"])
ส่วนหัว ( "WWW-รับรองความถูกต้อง: อาณาจักรพื้นฐาน = อาณาจักรของฉัน");
เสียงสะท้อน “ข้อความที่ส่งเมื่อ
หากผู้ใช้คลิกปุ่มยกเลิก";
ออก;
) อื่น (
เสียงสะท้อน"
เสียงสะท้อน "
}
?>
หมายเหตุความเข้ากันได้:โปรดใช้ความระมัดระวังเป็นพิเศษเมื่อระบุส่วนหัว HTTP เพื่อให้มั่นใจถึงความเข้ากันได้สูงสุดกับ จำนวนที่ใหญ่ที่สุดลูกค้าที่แตกต่างกัน คำว่า "Basic" จะต้องเขียนด้วยตัวพิมพ์ใหญ่ "B" ภูมิภาค (ขอบเขต) จะต้องอยู่ในเครื่องหมายคำพูดคู่ (ไม่ใช่เดี่ยว!) และต้องมีช่องว่างหนึ่งช่องอยู่ข้างหน้าโค้ด 401 ในชื่อ HTTP/1.0 401 .
แทนที่จะแสดงตัวแปร PHP_AUTH_USER และ PHP_AUTH_PW บนหน้าจอ คุณอาจต้องตรวจสอบว่าตัวแปรเหล่านั้นถูกต้อง เมื่อต้องการทำเช่นนี้ ใช้การร้องขอเพื่อ ฐานข้อมูลหรือค้นหาผู้ใช้ในไฟล์ dbm
คุณสามารถสังเกตคุณสมบัติของเบราว์เซอร์ได้ อินเทอร์เน็ตเอ็กซ์พลอเรอร์- เป็นเรื่องพิถีพิถันมากเกี่ยวกับพารามิเตอร์ของส่วนหัวที่ส่ง การระบุชื่อเรื่อง WWW-รับรองความถูกต้องก่อนที่จะส่งสถานะ HTTP/1.0 401 ถือเป็นเคล็ดลับเล็กน้อย
ใน PHP 4.3.0 เพื่อป้องกันไม่ให้ผู้อื่นเขียนสคริปต์ที่เปิดเผยรหัสผ่านสำหรับเพจที่ใช้การรับรองความถูกต้องภายนอก ตัวแปร PHP_AUTH จะไม่ถูกตั้งค่าหาก หน้านี้ใช้การรับรองความถูกต้องภายนอกและตั้งค่าเป็นโหมดปลอดภัย อย่างไรก็ตาม สามารถใช้ตัวแปร REMOTE_USER เพื่อตรวจสอบสิทธิ์ผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์จากภายนอกได้ ดังนั้นคุณสามารถใช้ตัวแปร $_SERVER["REMOTE_USER"] ได้ตลอดเวลา
บันทึก: PHP ใช้คำสั่ง AuthType เพื่อระบุว่ามีการใช้การรับรองความถูกต้องภายนอกหรือไม่
ควรสังเกตว่าสิ่งที่กล่าวมาทั้งหมดไม่ได้ป้องกันการขโมยรหัสผ่านไปยังเพจที่ต้องได้รับอนุญาตจากบุคคลที่ควบคุมเพจโดยไม่ได้รับอนุญาตซึ่งอยู่บนเซิร์ฟเวอร์เดียวกัน
ทั้ง Netscape Navigator และ Internet Explorer จะล้างแคชการรับรองความถูกต้องของหน้าต่างปัจจุบันสำหรับขอบเขตที่กำหนดเมื่อได้รับจากเซิร์ฟเวอร์ ซึ่งสามารถใช้เพื่อบังคับให้ผู้ใช้ออกจากระบบและแสดงกล่องโต้ตอบชื่อผู้ใช้และรหัสผ่านอีกครั้ง นักพัฒนาซอฟต์แวร์บางรายใช้สิ่งนี้เพื่อจำกัดเวลาเข้าสู่ระบบหรือจัดให้มีปุ่มออกจากระบบ
ตัวอย่างการตรวจสอบสิทธิ์ HTTP พร้อมการบังคับให้ป้อนข้อมูลคู่ล็อกอิน/รหัสผ่านใหม่
ฟังก์ชั่นตรวจสอบสิทธิ์ () (
ส่วนหัว ( "WWW-Authenticate: ขอบเขตพื้นฐาน = "ทดสอบระบบการรับรองความถูกต้อง"");
header("HTTP/1.0 401 ไม่ได้รับอนุญาต");
เสียงสะท้อน "คุณต้องป้อนชื่อผู้ใช้และรหัสผ่านที่ถูกต้องเพื่อเข้าถึงทรัพยากร \n";
ออก;
}
ถ้า (!isset($_SERVER [ "PHP_AUTH_USER" ]) || ยินดีต้อนรับ: ($_SERVER["PHP_AUTH_USER"])
($_POST [ "เห็นก่อน" ] == 1 && $_POST [ "OldAuth" ] == $_SERVER [ "PHP_AUTH_USER" ])) (
ตรวจสอบสิทธิ์ ();
}
อื่น(
เสียงสะท้อน"
"
เสียงสะท้อน "การเข้าสู่ระบบก่อนหน้า: ($_REQUEST["OldAuth"])";
เสียงสะท้อน ";
เสียงสะท้อน "\n";
เสียงสะท้อน "\n";
เสียงสะท้อน "\n";
เสียงสะท้อน "
}
?>
ลักษณะการทำงานนี้ไม่อยู่ภายใต้มาตรฐานการตรวจสอบสิทธิ์ HTTP Basic ดังนั้นคุณจึงไม่ควรพึ่งพาพฤติกรรมดังกล่าว การทดสอบแสดงให้เห็นว่าเบราว์เซอร์ Lynx ไม่ได้ล้างแคชการอนุญาตเมื่อได้รับสถานะ 401 จากเซิร์ฟเวอร์และโดยการคลิก "ย้อนกลับ" จากนั้น "ส่งต่อ" ตามลำดับก็เป็นไปได้ที่จะเปิดหน้าดังกล่าวโดยมีเงื่อนไขว่าการอนุญาตที่จำเป็น คุณสมบัติไม่เปลี่ยนแปลง อย่างไรก็ตาม ผู้ใช้สามารถกดปุ่ม "_" เพื่อล้างแคชการตรวจสอบสิทธิ์ได้
ควรสังเกตว่าก่อน PHP 4.3.3 การตรวจสอบสิทธิ์ HTTP จะไม่ทำงานบนเซิร์ฟเวอร์ที่ใช้ Microsoft IIS หากติดตั้ง PHP เป็นโมดูล CGI เนื่องจากข้อจำกัด IIS บางประการ เพื่อให้บรรลุผล การดำเนินการที่ถูกต้องใน PHP 4.3.3+ คุณต้องแก้ไขการตั้งค่า IIS ที่เรียกว่า "Directory Security" คลิกที่คำจารึก "แก้ไข" และตั้งค่าตัวเลือก "การเข้าถึงแบบไม่ระบุชื่อ" ช่องอื่น ๆ ทั้งหมดไม่ควรถูกเลือก
ข้อจำกัดอีกประการหนึ่งหากคุณใช้ IIS ผ่าน ISAPI: ไม่ได้กำหนดตัวแปร PHP_AUTH_* แต่ในขณะเดียวกัน ตัวแปร HTTP_AUTHORIZATION ก็พร้อมใช้งาน โค้ดตัวอย่างที่คุณสามารถใช้ได้: list($user, $pw) = explode(///, base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)));
หมายเหตุเกี่ยวกับ IIS::เพื่อให้การรับรองความถูกต้อง HTTP ทำงานอย่างถูกต้องใน IIS ตัวเลือก cgi.rfc2616_headers ในการกำหนดค่า PHP จะต้องตั้งค่าเป็น 0 (ค่าเริ่มต้น)
ความสนใจ:ในกรณีที่ใช้โหมดป้องกัน UID ของสคริปต์ปัจจุบันจะถูกเพิ่มไปยังส่วนขอบเขตของส่วนหัว WWW-Authenticate
<<< Назад | เนื้อหา | ไปข้างหน้า >>> |
หากคุณมีคำถามอื่นๆ หรือมีบางอย่างไม่ชัดเจน ยินดีต้อนรับเข้าสู่เรา | |
|
การจำกัดการเข้าถึงพื้นที่ใดๆ ของไซต์มักจะมีลักษณะดังนี้
ซ้ำซากจำเจ: ผู้ใช้แต่ละคนจะได้รับข้อมูลเข้าสู่ระบบและรหัสผ่านหรือตัวเขาเอง
เลือกพวกเขาและเพื่อเข้าสู่ส่วนที่ปลอดภัยของไซต์พวกเขาจะต้องป้อน จากมุมมองทางเทคนิค ให้ตรวจสอบรหัสผ่านที่พวกเขาใช้
วิธีการที่แตกต่างกัน คุณสามารถใช้แบบฟอร์ม HTML เพื่อเข้าสู่ระบบและรหัสผ่านของคุณได้
ในกรณีนี้ รหัสผ่านจะถูกส่งไปยังเซิร์ฟเวอร์ในรูปแบบข้อความที่ชัดเจนในคำขอ POST
สิ่งนี้เป็นสิ่งที่ยอมรับไม่ได้หากผู้ใช้อยู่ในพื้นที่ หากเป็นไปได้
ใช้ดมกลิ่น เพื่อแก้ไขปัญหานี้จึงได้มีการคิดค้นวิธีการขึ้นมา
การรับรองความถูกต้องโดยใช้แฮชซึ่งไม่ได้ส่งรหัสผ่าน แต่
สตริงแฮชจะถูกส่งเพียงครั้งเดียว ขึ้นอยู่กับรหัสผ่าน
พารามิเตอร์และอาจมาจากพารามิเตอร์อื่นๆ วิธีนี้ก็เช่นกัน
เรียกว่าการท้าทาย/การตอบสนอง เพราะเมื่อใช้มันลูกค้า
รับคำขอพร้อมพารามิเตอร์ครั้งเดียวและส่งการตอบกลับที่มีแฮช ที่ระดับโปรโตคอล HTTP 1.1 ให้ตรวจสอบสิทธิ์โดยใช้
พื้นฐานซึ่งไม่มีอะไรเลย ใช้ดีกว่ารูปแบบ HTML และ Digest ซึ่ง
เราจะดูรายละเอียด
เมื่อใช้วิธีการ Digest ดังที่ได้กล่าวไปแล้วรหัสผ่าน
ไม่แพร่เชื้อและสูดดมไม่ได้ แต่ก็มีอีกด้านหนึ่ง
ปัญหา. ในการตรวจสอบรหัสผ่านเซิร์ฟเวอร์จะต้องคำนวณ
ตอบสนองและเปรียบเทียบกับการตอบสนองของลูกค้า ดังนั้นเซิร์ฟเวอร์จึงต้อง
เก็บรหัสผ่านหรือข้อมูลขึ้นอยู่กับความจำเป็น
ผ่านการรับรองความถูกต้อง ตามมาว่าบุคคลที่ได้รับสิทธิ
เพื่ออ่านบัญชี (เช่น ใช้ SQL injector) ก็จะสามารถรับได้
เข้าถึงเพจที่ได้รับการป้องกันโดยวิธี Digest เมื่อใช้วิธีการ
ขั้นพื้นฐาน คุณสามารถจัดเก็บแฮชแทนรหัสผ่านได้ ซึ่งไม่อนุญาตให้คุณเพิ่มสิทธิ์
หลังจากอ่านแฮชเหล่านี้แล้ว (เราจะดูด้านล่างว่า Digest ยังสามารถเก็บแฮชได้
แต่ความรู้ก็เพียงพอที่จะคำนวณคำตอบได้) ดังนั้นเราจึงเผชิญกับภาวะที่กลืนไม่เข้าคายไม่ออก: รหัสผ่านของเราจะถูกดักฟัง
หรือพวกเขาจะเอามันผ่านช่องโหว่ของเว็บซึ่งใครบางคนจะต้องเจออย่างแน่นอน
เพราะผู้ที่แสวงหาก็จะพบเสมอ มีวิธีการตรวจสอบสิทธิ์ที่ไม่มี
ข้อเสียทั้งสองประการนี้คือวิธีการรับรองความถูกต้องของกุญแจสาธารณะ:
เพื่อตรวจสอบว่าคุณต้องการรหัสสาธารณะ และเพื่อผ่านการตรวจสอบ คุณต้องใช้รหัสลับ
อย่างไรก็ตาม HTTP 1.1 ไม่มีวิธีการดังกล่าว อาร์เอฟซี 2069
แนะนำให้ใช้ SSL หากความปลอดภัยมีความสำคัญมาก มีเพียงการส่งรหัสผ่านเท่านั้นที่ได้รับการปกป้อง และเนื้อหาก็ไม่ได้รับการเข้ารหัสเช่นกัน
ว่าไม่มีประโยชน์ในการปกป้องทรัพยากรด้วยวิธีนี้ว่าผู้ใช้มาจากไหน
ได้รับ ข้อมูลลับ- พวกเขาต้องการ SSL และมันก็สมเหตุสมผล
ปกป้อง เช่น ฟอรัม หรือการอัพโหลดเนื้อหาไปยังเว็บไซต์ ดังนั้นหากโฮสติ้งไม่รองรับ SSL และต้องมีการรับรองความถูกต้อง
เพื่อความปลอดภัยเราจะใช้ไดเจสต์ Apache มีโมดูล mod_digest หากต้องการใช้มัน
ในการกำหนดค่า (หรือใน .htaccess) เราเขียน:
AuthType ไดเจสต์
AuthUserFile<файл>
ชื่อรับรองความถูกต้อง<название защищаемой области>
จำเป็นต้องมี valid_user
ไฟล์ผู้ใช้ถูกสร้างขึ้นโดยยูทิลิตี้
htdigest. ครั้งหนึ่งมีรายงานเกี่ยวกับ mod_digest ว่ามีช่องโหว่ ดังนั้น
บางทีปัญหาอื่น ๆ อาจปรากฏขึ้นที่นั่น นอกจากนี้เมื่อ
ฉันพยายามใช้ที่บ้าน ฉันได้รับข้อผิดพลาด
ข้อผิดพลาดภายในเซิร์ฟเวอร์ 500 นอกจากนี้หากควรทำการเพิ่มบัญชี
โดยอัตโนมัติและควรมีจำนวนมากพอสมควร
เก็บไว้ในการกำหนดค่า Apache แต่อยู่ใน MySQL สารละลาย -
ใช้ PHP PHP ไม่มีการสนับสนุนในตัวสำหรับสิ่งนี้
จึงต้องนำไปปฏิบัติ ในการทำเช่นนี้คุณต้องศึกษา
วิธีนี้อย่างละเอียด ให้ฉันทราบทันทีที่ให้ไว้ในบทความนี้
การใช้งานใช้งานได้กับ Apache เท่านั้นเนื่องจาก การเข้าถึงแบบเต็มไปที่ส่วนหัว
request (ฟังก์ชัน apache_request_headers) ใช้งานได้ใน Apache เท่านั้น แต่เปิดอยู่
อาจไม่สามารถใช้ได้บนเซิร์ฟเวอร์อื่น เราแค่ต้องอ่าน
ส่วนหัวของการอนุญาต
คำอธิบายของวิธีการ
คำอธิบายแบบเต็มของวิธีการสามารถอ่านได้ใน RFC 2069 และหาก
สรุปวิธีนี้ใช้ได้ผลดังนี้ เมื่อเซิร์ฟเวอร์ได้รับคำขอที่เกี่ยวข้องกับพื้นที่ที่ได้รับการคุ้มครอง
มันเกิดข้อผิดพลาด 401 Authorization Required และส่วนหัวของคำขอ
การรับรองความถูกต้องประเภทนี้:
WWW-รับรองความถูกต้อง: แยก realm = "พื้นที่ปลอดภัย", nonce = "123456123456"
realm คือชื่อของพื้นที่คุ้มครอง และ nonce เป็นการใช้งานเพียงครั้งเดียว
ความหมาย. นอกจากนี้ยังมีพารามิเตอร์ทางเลือกที่เราจะกล่าวถึง
เราจะไม่ ลูกค้าทำซ้ำคำขอ โดยเพิ่มส่วนหัวดังนี้:
การอนุญาต: Digest realm="secure area", username="123", uri="/index.php", nonce="123456123456", response="1234567890abcdef1234567890abcdef"
พารามิเตอร์ uri ต้องตรงกับ URI ในคำขอ และการตอบกลับคือ
คำตอบซึ่งคำนวณได้ดังนี้:
การตอบสนอง = H(H(A1) + ร้อยละ + nonce + ร้อยละ + H(A2))
H - ฟังก์ชันแฮช, MD5 เริ่มต้น
A1 = เข้าสู่ระบบ + /// + ขอบเขต + /// + รหัสผ่าน
A2 = วิธีการร้องขอ + /// + URI
วิธีการร้องขอคือ GET, POST ฯลฯ
ดังที่เราเห็น A1 ไม่ได้ขึ้นอยู่กับคำขอหรือครั้งเดียว
ค่า ดังนั้นเซิร์ฟเวอร์อาจไม่ได้จัดเก็บรหัสผ่าน แต่
เอช(A1) นี่คือวิธีการนำไปใช้ใน mod_digest ใน Apache
อย่างไรก็ตาม ข้อมูลเดียวกันก็เพียงพอสำหรับลูกค้า ผู้โจมตีได้รับแล้ว
แฮชนี้สามารถคำนวณคำตอบโดยใช้สูตรข้างต้นและ
สร้างคำขอ HTTP เช่น การใช้โปรแกรม
AccessDriver และเครื่องมือ HTTP
ดีบักเกอร์ กระบวนการนี้จะแสดงรายละเอียดเพิ่มเติมด้านล่าง เซิร์ฟเวอร์จะต้องตรวจสอบว่าค่าเป็น nonce หรือไม่
อันที่ออกให้กับลูกค้าก่อนหน้านี้และไม่ว่าจะล้าสมัยหรือไม่
หากการตอบสนองตรงกับพารามิเตอร์ nonce แต่เป็นค่าของพารามิเตอร์นั้น
ไม่เกี่ยวข้อง การตอบสนองที่อธิบายไว้ข้างต้นด้วยรหัส 401 ออกเพียงเพราะว่า
ข้อแตกต่างคือพารามิเตอร์ถูกเพิ่มลงในส่วนหัว WWW-Authenticate
stale=true ระบุว่าการเข้าถึงถูกปฏิเสธด้วยเหตุผลนี้เท่านั้น
และควรลองอีกครั้งโดยไม่แจ้งให้ผู้ใช้ใส่รหัสผ่านใหม่ สิ่งนี้ IMHO ไม่สะดวกเพราะหากเกิดสถานการณ์เช่นนี้
เมื่อทำการร้องขอ POST หรือ PUT ด้วยบล็อกข้อมูลขนาดใหญ่ ลูกค้าจะต้องดำเนินการ
ส่งข้อมูลทั้งหมดสองครั้ง เพื่อหลีกเลี่ยงปัญหานี้ มาตรฐานจึงจัดเตรียมไว้ให้
ส่วนหัวข้อมูลการรับรองความถูกต้องซึ่งเซิร์ฟเวอร์อาจตอบสนอง
คำขอสำเร็จเพื่อบอกลูกค้าในครั้งถัดไป
ไวยากรณ์เหมือนกับ WWW-Authenticate ยกเว้นว่า nonce
ถูกแทนที่ด้วย nextnonce อย่างไรก็ตามตัดสินจากผลลัพธ์ของฉัน
การทดลอง Opera จะละเว้นส่วนหัวนี้ วิธีแก้ปัญหาอื่น: ตาม
RFC 2068 (HTTP/1.1) เซิร์ฟเวอร์อาจตอบสนองก่อนที่คำขอจะเสร็จสมบูรณ์
เพื่อให้ไคลเอนต์ขัดจังหวะการถ่ายโอนข้อมูลที่ไม่จำเป็น แต่ใน Apache+PHP เป็นเช่นนั้น
ไม่ได้ถูกนำมาใช้ เนื่องจากสคริปต์เริ่มทำงานหลังจากนั้นเท่านั้น
Apache จะได้รับและแยกวิเคราะห์คำขออย่างเต็มที่อย่างไร
จัดเก็บข้อมูลระหว่างคำขอ
มีจุดละเอียดอ่อนในการใช้วิธีท้าทาย/ตอบสนองใน PHP
พารามิเตอร์แบบครั้งเดียวจะถูกสร้างขึ้นและออกให้กับลูกค้าในการตอบกลับครั้งเดียวและ
ถูกตรวจสอบในเซสชันอื่นของสคริปต์
นั่นคือจะต้องบันทึกจากการเรียกสคริปต์หนึ่งไปยังอีกสคริปต์หนึ่งและคุณจะต้องทำสิ่งนี้
ใช้ไฟล์หรือฐานข้อมูล ตัวอย่างของฉันใช้ไฟล์ชื่อ
สอดคล้องกับค่าที่เกิดขึ้นเพียงครั้งเดียว และไฟล์ต่างๆ ก็มีอยู่ด้วย
ที่อยู่ IP ของลูกค้าที่ออกให้ ไม่ได้ใช้การรวบรวมในตัวอย่าง
ขยะ: คุณต้องลบไฟล์เก่าเป็นระยะ
การแยกวิเคราะห์โค้ด
สคริปต์นี้จะตรวจสอบรหัสผ่านเท่านั้นและใช้งานได้โดยไม่คำนึงถึง
เข้าสู่ระบบ คำตอบง่ายๆ จะได้รับขึ้นอยู่กับความสำเร็จของการตรวจสอบ
$อาณาจักร = "พื้นที่ปลอดภัย"; - ชื่อพื้นที่คุ้มครอง
$ผ่าน = "ผ่าน"; // รหัสผ่าน
$fileprefix = "./"; - เส้นทางสำหรับไฟล์แท็กที่ระบุความถูกต้องของ nonce
/*
มาสร้างพารามิเตอร์แบบครั้งเดียวตามที่แนะนำใน RFC2069 แม้ว่าจะสามารถทำได้แตกต่างออกไปก็ตาม พารามิเตอร์ตามที่แนะนำควรขึ้นอยู่กับที่อยู่ไคลเอ็นต์ เวลาปัจจุบัน และสตริงที่เป็นความลับ */
$nonce = md5($_SERVER["REMOTE_ADDR"] . /// . time() . ":MyCooolPrivateKey");
// รับส่วนหัว
$headers = apache_request_headers();
// ธงที่เราจะตั้งค่าเป็น TRUE เมื่อตรวจสอบสำเร็จ
$auth_success = เท็จ;
$เก่า = "";
// หากไม่มีส่วนหัวการอนุญาต แสดงว่าไม่มีอะไรต้องตรวจสอบ
ถ้า (isset($headers["การอนุญาต"]))
{
$authorization = $headers["การอนุญาต"];
/* เรามาแยกวิเคราะห์ชื่อโดยใช้นิพจน์ทั่วไป ชื่อเรื่องประกอบด้วยคำว่า "Digest" และรายการ
พารามิเตอร์ของรูปแบบ param="value" หรือ param=value คั่นด้วยเครื่องหมายจุลภาค นิพจน์ทั่วไปนี้ตรงกับพารามิเตอร์ดังกล่าวหนึ่งรายการ */
preg_match_all("/(,|\s|^)(\w+)=("([^"]*)"|([\w\d]*))(,|$)/",
$การอนุญาต, $matches, PREG_SET_ORDER);
/* ตอนนี้ เพื่อความสะดวกในการประมวลผลต่อไป มาสร้างอาร์เรย์ โดยที่คีย์คือชื่อของพารามิเตอร์ และค่าขององค์ประกอบอาร์เรย์คือ
ค่าพารามิเตอร์ */
$auth_params = อาร์เรย์();
สำหรับ ($i = 0; $i< count($matches); $i++)
{
$match = $matches[$i];
/* ชื่อจะอยู่ในวงเล็บกลุ่มที่สองเสมอ ขึ้นอยู่กับว่าจะอยู่ในเครื่องหมายคำพูดหรือไม่ก็ตาม
อยู่ในกลุ่มที่ 4 หรือ 5 สำหรับกลุ่มวงเล็บที่ตก
ไปยังสาขาที่ยังไม่ได้ใช้งาน สตริงว่างในอาร์เรย์
เพื่อให้คุณสามารถเพิ่มค่าต่างๆ ได้*/
$auth_params[$match] = $match $ตรงกัน;
}
/* ลองคำนวณคำตอบซึ่งสอดคล้องกับ
การเข้าสู่ระบบที่ผู้ใช้ป้อน รหัสผ่านของเรา และพารามิเตอร์แบบครั้งเดียวที่ผู้ใช้ส่งผ่าน
*/
$a1 = $auth_params["ชื่อผู้ใช้"] - $auth_params["อาณาจักร"] - $ผ่าน;
$a2 = $_SERVER["REQUEST_METHOD"] - $_SERVER["REQUEST_URI"];
$resp = md5(md5($a1) . अप्रैल . $auth_params["nonce"] . ซิลิโคน . md5($a2));
// เรามาตรวจสอบคำตอบกันดีกว่า
ถ้า ($resp == $auth_params["ตอบกลับ"])
{
//
การตรวจสอบความเกี่ยวข้องของพารามิเตอร์แบบครั้งเดียว
$fn = $คำนำหน้าไฟล์ $auth_params["ไม่มี"];
ถ้า (@file_get_contents($fn) == $_SERVER["REMOTE_ADDR"])
{
ยกเลิกการเชื่อมโยง($fn); -ตัวเลือกนี้ไม่เกี่ยวข้องอีกต่อไป
$auth_success = จริง; -การตรวจสอบสิทธิ์ผ่านไปแล้ว
) อื่น
{
//
พารามิเตอร์แบบครั้งเดียวไม่เกี่ยวข้อง
$stale = ", เก่า = true";
}
}
}
ถ้า ($auth_success)
{
พิมพ์("
print("ยืนยันตัวตนเรียบร้อยแล้ว\n");
var_dump($auth_params);
พิมพ์("");
) อื่น
{
file_put_contents($fileprefix . $nonce, $_SERVER["REMOTE_ADDR"]);
$โปรโต = $_SERVER["SERVER_PROTOCOL"];
ส่วนหัว("$โปรโต 401 ไม่ได้รับอนุญาต");
Header("WWW-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\"$stale");
พิมพ์("
");");
print("คุณต้องรับรองความถูกต้องด้วยวิธี Digest");
พิมพ์("
}
ผ่าน Digest Auth ด้วย H (A1) ที่รู้จัก
ฉันจะแสดงตัวอย่างวิธีการผ่านการยืนยันหากไม่ทราบรหัสผ่าน
แต่ H(A1) เป็นที่รู้จัก สำหรับสิ่งนี้ดังที่ได้กล่าวไปแล้วคุณจะต้องมี
แอคเซสไดร์เวอร์ ฉันจะคำนวณแฮชโดยการโทรจากบรรทัดคำสั่ง
PHP CLI ให้เพจที่มีการป้องกันอยู่ที่
http://mrblack.local/auth1.php และแฮช H(A1) คือ "a8fb5b2d780a7bf0782207a51a013f04"
เปิด AccessDriver->เครื่องมือ->HTTP Debugger แล้วป้อนที่อยู่
"http://mrblack.local/auth1.php" คลิก "เชื่อมต่อ" เราได้รับ:
ส่วนหัว HTTP = จำเป็นต้องมีการอนุญาต HTTP/1.1 401
ส่วนหัว HTTP = วันที่: จันทร์ 04 ก.ค. 2548 08:09:17 GMT
ส่วนหัว HTTP = เซิร์ฟเวอร์: Apache/1.3.31 (Win32) PHP/5.0.2
ส่วนหัว HTTP = X-ขับเคลื่อนโดย: PHP/5.0.2
ส่วนหัว HTTP = WWW- รับรองความถูกต้อง: แยก realm = "พื้นที่ปลอดภัย", nonce = "5925bea78552224abda11bfe318a8a03"
ส่วนหัว HTTP = การเชื่อมต่อ: ปิด
ส่วนหัว HTTP = ประเภทเนื้อหา: text/html
เปิดคอนโซลไปที่โฟลเดอร์ด้วย PHP แล้วป้อนคำสั่งต่อไปนี้:
php -r "พิมพ์ md5("a8fb5b2d780a7bf0782207a51a013f04:
: ".md5("GET:http://mrblack.local/auth1.php"));"
เราได้รับคำตอบสรุปที่ต้องการ: c6d0af0db239d75c
3f59640a4896d096
ตอนนี้ใน AccessDriver ให้ทำเครื่องหมายที่ช่อง "ข้อมูลส่วนหัว" คัดลอกไปยังส่วนที่ปรากฏขึ้น
ส่วนหัวของฟิลด์ที่ถูกส่งไปในคำขอก่อนหน้า และเพิ่มเข้าไป
การอนุญาต นี่คือสิ่งที่เกิดขึ้น:
รับ http://mrblack.local/auth1.php HTTP/1.1
ยอมรับ: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
ยอมรับภาษา: en-us,en;q=0.5
ตัวแทนผู้ใช้: รองรับ Mozilla
โฮสต์: mrblack.local
Pragma: ไม่มีแคช
การอนุญาต: แยกชื่อผู้ใช้ = "mrblack", realm = "พื้นที่ปลอดภัย", nonce = "5925bea78552224ab
da11bfe318a8a03", uri="http://mrblack.local/auth1.php", การตอบสนอง = "c6d0af0db239d75c3f59
640a4896d096"
คลิก "เชื่อมต่อ" เราได้รับผลลัพธ์:
บางครั้งจำเป็นต้องปิดจากการเข้าถึงจากภายนอก PHPหน้าหากคุณกำลังสร้างพื้นที่ปิดของไซต์ นี่อาจเป็นข้อมูลที่ซ่อนอยู่สำหรับลูกค้าหรือผู้เยี่ยมชมไซต์ของคุณ อินเทอร์เฟซการดูแลระบบบางอย่างสำหรับคุณ เป็นต้น คุณสามารถคิดงานต่างๆ มากมายที่ต้องมีข้อจำกัดในการเข้าถึงได้
คุณสามารถปิดหน้าดังกล่าวได้หลายวิธี:
- การป้องกันด้วยรหัสผ่าน (เข้าสู่ระบบ/รหัสผ่าน) โดยใช้ตัวแปร $_SERVER["PHP_AUTH_USER"]และ $_SERVER["PHP_AUTH_PW"].
- คุ้มครองโดย ไอพีที่อยู่ไคลเอ็นต์โดยใช้ตัวแปร $_SERVER["REMOTE_ADDR"].
- คุ้มครองโดย แม็คที่อยู่ในเครือข่ายท้องถิ่น (นอกเหนือจากการป้องกันโดย ไอพี).
มาดูวิธีแรกกันก่อนซึ่งเป็นวิธีหลัก ช่วยให้คุณสามารถบล็อกการเข้าถึงเพจโดยใช้ข้อมูลเข้าสู่ระบบและรหัสผ่านของคุณ ดังนั้นผู้ที่ทราบข้อมูลเข้าสู่ระบบและรหัสผ่านเท่านั้นจึงจะสามารถเข้าถึงได้ นอกจากนี้ยังสามารถแบ่งตามเกณฑ์นี้และสามารถให้ข้อมูลที่แตกต่างกันสำหรับแต่ละรายการได้ ดำเนินการโดยการออกช่องพิเศษในส่วนหัวของโปรโตคอล HTTP- มาสร้างฟังก์ชั่นกัน auth_send():
" ,"
ข้อผิดพลาดในการรับรองความถูกต้อง
" ,"ติดต่อผู้ดูแลระบบเพื่อขอรับข้อมูลเข้าสู่ระบบและรหัสผ่านของคุณ
" ,""; ออก; ); ?>ฟังก์ชันนี้แจ้งให้เบราว์เซอร์ทราบว่าการเข้าถึงต้องได้รับอนุญาตโดยใช้ข้อมูลเข้าสู่ระบบและรหัสผ่าน และยังแสดงหน้าอีกด้วย HTMLสำหรับผู้ใช้
" ,"
ยินดีต้อนรับ!
" ,"คุณเข้าสู่ระบบโดยใช้ล็อกอิน ",$auth_user" และรหัสผ่าน ",$auth_pass"
" ,""; ?>รหัสยืนยันการเข้าสู่ระบบและรหัสผ่านไม่ซับซ้อนเกินไปในกรณีนี้ เนื่องจากมีการใช้งานสำหรับบุคคลเดียว ตรรกะการดำเนินงานนั้นง่ายหากไม่มีตัวแปร $_SERVER["PHP_AUTH_USER"]และ $_SERVER["PHP_AUTH_PW"]หรือค่าไม่ตรงกับที่ต้องการให้เรียกใช้ฟังก์ชัน auth_send()- อย่าลืมว่าตอนท้ายมันโทรมา ออกดังนั้นการทำงานของโปรแกรมจึงหยุดลง
การป้องกันระดับต่อไปจะดำเนินการโดยการกรอง ไอพีที่อยู่ของลูกค้าที่เชื่อมต่อ แน่นอนว่าบนอินเทอร์เน็ตผู้ให้บริการหลายรายมีปัญหา ไอพีที่อยู่ชั่วคราวและการป้องกันนี้ไม่มีประโยชน์ แต่หากเรากำลังพูดถึงเครือข่ายท้องถิ่นขององค์กร การตรวจสอบนี้จะให้การป้องกันเพิ่มเติม
ไม่พบ IP ของคุณ!!!"; exit; ); ?>
อยู่แถวนี้แหละ. $allowed_ipsระบุโดยคั่นด้วยช่องว่าง ไอพีที่อยู่ที่ได้รับอนุญาตให้เข้าถึง ต่อไปเราจะนำอาร์เรย์ไปใช้ ระเบิด()และค้นหาที่อยู่ของลูกค้าจาก $_SERVER["REMOTE_ADDR"]- ฉันใช้ฟังก์ชันเพื่อค้นหา array_search()เนื่องจากไม่น่าเป็นไปได้ที่โค้ดที่ใช้ในภาษา C จะทำงานได้เร็วกว่าที่เราเขียนลงไป PHPใช้ลูป สำหรับหรือ foreach- แต่ความเร็วไม่ใช่สิ่งสำคัญที่นี่ :)
และขั้นตอนสุดท้ายของการป้องกันคือการตรวจสอบ แม็คที่อยู่ จัดอยู่ในประเภทหวาดระแวงและควรใช้หากคุณเข้าถึงจากเครือข่ายท้องถิ่นและข้อมูลที่คุณปกป้องมีความสำคัญมากจริงๆ จนถึงตอนนี้ฉันได้ใช้การตรวจสอบนี้กับระบบเท่านั้น ลินุกซ์เนื่องจากความเรียบง่ายของการนำไปปฏิบัติ แต่คุณสามารถลองใช้กับแพลตฟอร์มอื่นได้ เราเขียนฟังก์ชัน:
ตามที่ผู้ใช้ Linux เข้าใจกันแล้วว่าจะขึ้นอยู่กับ เออาร์พีตารางระบบซึ่งสามารถเข้าถึงได้โดยใช้ไฟล์ /proc/net/arp- ฟังก์ชันค้นหาสตริงสำหรับสิ่งที่จำเป็น ไอพีที่อยู่แล้วส่งคืน แม็คที่อยู่:
IP ของคุณ=192.168.10.15 และ MAC=00:04:31:E4:F8:37
ในระบบ หน้าต่างบางทีอาจมีบางวิธีที่จะได้รับ แม็คง่ายกว่า แต่จากที่ใช้งานได้จริงนี่คือข้อสรุป เออาร์พีตารางระบบด้วยคำสั่ง:
อินเทอร์เฟซ C:\WINDOWS\>arp -a: 192.168.10.15 บนอินเทอร์เฟซ 0x1000003 ที่อยู่ IP ประเภทที่อยู่ทางกายภาพ 192.168.10.1 00-50-22-b0-6a-aa ไดนามิก 192.168.10.2 00-0f-38-68-e9- e8 ไดนามิก 192.168.10.3 00-04-61-9e-26-09 ไดนามิก 192.168.10.5 00-0f-38-6a-b1-18 ไดนามิก
คุณสามารถใช้การป้องกันตามที่อยู่นี้ด้วยตนเองได้หากต้องการจริงๆ :) แต่จำไว้ว่าหากคุณมีอุปกรณ์ที่ไม่มีการจัดการบนเครือข่ายของคุณโดยไม่มีความสามารถในการผูกมัด แม็คที่อยู่ในพอร์ต การป้องกันนี้อาจไม่ทำงาน เนื่องจากข้อมูลประจำตัวทั้งหมดของคุณที่ใช้สำหรับการป้องกัน (การเข้าสู่ระบบ รหัสผ่าน IP และที่อยู่ MAC) สามารถปลอมแปลงได้