การรับรองความถูกต้องสำหรับ PHP เรียบง่าย น้ำหนักเบา และปลอดภัย
เขียนครั้งเดียว นำไปใช้ได้ทุกที่
ไม่เชื่อเรื่องพระเจ้าแบบเฟรมเวิร์กและไม่เชื่อเรื่องฐานข้อมูลโดยสมบูรณ์
pdo
)mysqlnd
) หรือ ไดรเวอร์ PostgreSQL ( pgsql
) หรือ ไดรเวอร์ SQLite ( sqlite
)openssl
)รวมไลบรารีผ่าน Composer [?]:
$ composer require delight-im/auth
รวมตัวโหลดอัตโนมัติของ Composer:
require __DIR__ . ' /vendor/autoload.php ' ;
ตั้งค่าฐานข้อมูลและสร้างตารางที่จำเป็น:
ต้องการย้ายข้อมูลจากเวอร์ชันก่อนหน้าของโปรเจ็กต์นี้ใช่ไหม ดูคำแนะนำในการอัปเกรดของเราสำหรับความช่วยเหลือ
// $ db = new PDO ( ' mysql:dbname=my-database ; host = localhost ; charset = utf8mb4' , ' my-username' , ' my-password' ) ;
// or
// $ db = new PDO ( ' pgsql:dbname=my-database ; host = localhost ; port = 5432 ' , ' my-username' , ' my-password' ) ;
// or
// $ db = new PDO ( ' sqlite:../Databases/my-database.sqlite' ) ;
// or
// $ db = Delight D b P doDatabase::fromDsn ( new Delight D b P doDsn ( ' mysql:dbname=my-database ; host = localhost ; charset = utf8mb4' , ' my-username' , ' my-password' ) ) ;
// or
// $ db = Delight D b P doDatabase::fromDsn ( new Delight D b P doDsn ( ' pgsql:dbname=my-database ; host = localhost ; port = 5432 ' , ' my-username' , ' my-password' ) ) ;
// or
// $ db = Delight D b P doDatabase::fromDsn ( new Delight D b P doDsn ( ' sqlite:../Databases/my-database.sqlite' ) ) ;
$ auth = new Delight Auth Auth ( $ db );
หากคุณมีการเชื่อมต่อ PDO
แบบเปิดอยู่แล้ว ให้ใช้งานอีกครั้ง ผู้ใช้ฐานข้อมูล (เช่น my-username
) ต้องการสิทธิ์อย่างน้อย SELECT
, INSERT
, UPDATE
และ DELETE
สำหรับตารางที่ใช้โดยไลบรารีนี้ (หรือฐานข้อมูลหลัก)
หากเว็บเซิร์ฟเวอร์ของคุณอยู่หลังพร็อกซีเซิร์ฟเวอร์และ $_SERVER['REMOTE_ADDR']
มีเฉพาะที่อยู่ IP ของพร็อกซี คุณต้องส่งที่อยู่ IP จริงของผู้ใช้ไปยังตัวสร้างในอาร์กิวเมนต์ที่สอง ซึ่งชื่อว่า $ipAddress
ค่าเริ่มต้นคือที่อยู่ IP ระยะไกลปกติที่ PHP ได้รับ
หากตารางฐานข้อมูลของคุณสำหรับไลบรารีนี้จำเป็นต้องมีคำนำหน้าร่วมกัน เช่น my_users
แทนที่จะเป็น users
(และในทำนองเดียวกันสำหรับตารางอื่นๆ) ให้ส่งคำนำหน้า (เช่น my_
) เป็นพารามิเตอร์ตัวที่สามให้กับตัวสร้างซึ่งมีชื่อว่า $dbTablePrefix
นี่เป็นทางเลือกและคำนำหน้าจะว่างเปล่าตามค่าเริ่มต้น
ในระหว่างการพัฒนา คุณอาจต้องการปิดการใช้งานการจำกัดคำขอหรือการควบคุมปริมาณที่ดำเนินการโดยไลบรารีนี้ ในการทำเช่นนั้น ให้ส่งค่า false
ไปยังตัวสร้างเป็นอาร์กิวเมนต์ที่สี่ ซึ่งมีชื่อว่า $throttling
คุณลักษณะนี้เปิดใช้งานตามค่าเริ่มต้น
ในช่วงอายุการใช้งานของเซสชัน ข้อมูลผู้ใช้บางส่วนอาจมีการเปลี่ยนแปลงจากระยะไกล โดยไคลเอ็นต์ในเซสชันอื่นหรือโดยผู้ดูแลระบบ นั่นหมายความว่าข้อมูลนี้จะต้องซิงโครไนซ์กับแหล่งข้อมูลที่เชื่อถือได้ในฐานข้อมูลเป็นประจำ ซึ่งไลบรารีนี้จะดำเนินการโดยอัตโนมัติ โดยค่าเริ่มต้น สิ่งนี้จะเกิดขึ้นทุกๆ ห้านาที หากคุณต้องการเปลี่ยนช่วงเวลานี้ ให้ส่งช่วงเวลาที่กำหนดเองในหน่วยวินาทีไปยังตัวสร้างเป็นอาร์กิวเมนต์ที่ห้า ซึ่งมีชื่อว่า $sessionResyncInterval
หากตารางฐานข้อมูลทั้งหมดของคุณต้องการชื่อฐานข้อมูลทั่วไป ชื่อสคีมา หรือตัวระบุอื่น ๆ ที่ต้องระบุอย่างชัดเจน คุณสามารถเลือกส่งตัวระบุนั้นไปยังตัวสร้างเป็นพารามิเตอร์ตัวที่หกซึ่งมีชื่อว่า $dbSchema
หากคุณต้องการใช้อินสแตนซ์ PdoDatabase
(เช่น $db
) อย่างอิสระเช่นกัน โปรดดูเอกสารประกอบของไลบรารีฐานข้อมูล
try {
$ userId = $ auth -> register ( $ _POST [ ' email ' ], $ _POST [ ' password ' ], $ _POST [ ' username ' ], function ( $ selector , $ token ) {
echo ' Send ' . $ selector . ' and ' . $ token . ' to the user (e.g. via email) ' ;
echo ' For emails, consider using the mail(...) function, Symfony Mailer, Swiftmailer, PHPMailer, etc. ' ;
echo ' For SMS, consider using a third-party service and a compatible SDK ' ;
});
echo ' We have signed up a new user with the ID ' . $ userId ;
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Invalid email address ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password ' );
}
catch ( Delight Auth UserAlreadyExistsException $ e ) {
die ( ' User already exists ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หมายเหตุ: ฟังก์ชันการโทรกลับแบบไม่ระบุชื่อเป็นการปิดตัวลง ดังนั้น นอกเหนือจากพารามิเตอร์ของตัวเองแล้ว มีเพียง superglobals เช่น $_GET
, $_POST
, $_COOKIE
และ $_SERVER
เท่านั้นที่สามารถใช้ได้ภายใน สำหรับตัวแปรอื่นๆ จากขอบเขตหลัก คุณต้องทำให้สำเนาพร้อมใช้งานภายในอย่างชัดเจนโดยการเพิ่มคำสั่ง use
หลังรายการพารามิเตอร์
ชื่อผู้ใช้ในพารามิเตอร์ที่สามเป็นทางเลือก คุณสามารถส่ง null
ได้หากคุณไม่ต้องการจัดการชื่อผู้ใช้
ในทางกลับกัน หากคุณต้องการบังคับใช้ชื่อผู้ใช้ที่ไม่ซ้ำ เพียงโทร registerWithUniqueUsername
แทน register
และเตรียมพร้อมที่จะตรวจจับ DuplicateUsernameException
หมายเหตุ: เมื่อยอมรับและจัดการชื่อผู้ใช้ คุณอาจต้องการยกเว้นอักขระควบคุมที่ไม่สามารถพิมพ์ได้และอักขระพิเศษบางตัวที่สามารถพิมพ์ได้ ดังเช่นในคลาสอักขระ [x00-x1fx7f/:\]
ในการดำเนินการดังกล่าว คุณสามารถล้อมการเรียก Auth#register
หรือ Auth#registerWithUniqueUsername
ภายในสาขาที่มีเงื่อนไขได้ ตัวอย่างเช่น โดยการยอมรับเฉพาะชื่อผู้ใช้เมื่อตรงตามเงื่อนไขต่อไปนี้:
if ( preg_match ( ' /[x00-x1fx7f/: \\ ]/ ' , $ username ) === 0 ) {
// ...
}
สำหรับการยืนยันอีเมล คุณควรสร้าง URL ที่มีตัวเลือกและโทเค็น และส่งไปยังผู้ใช้ เช่น:
$ url = ' https://www.example.com/verify_email?selector= ' . urlencode ( $ selector ) . ' &token= ' . urlencode ( $ token );
หากคุณไม่ต้องการดำเนินการยืนยันอีเมล เพียงละเว้นพารามิเตอร์สุดท้ายเป็น Auth#register
เช่น ฟังก์ชันที่ไม่ระบุชื่อหรือการปิด ผู้ใช้ใหม่จะเข้าใช้งานได้ทันทีแล้ว
ต้องการจัดเก็บข้อมูลผู้ใช้เพิ่มเติมหรือไม่? อ่านต่อที่นี่
หมายเหตุ: เมื่อส่งอีเมลถึงผู้ใช้ โปรดทราบว่า ณ จุดนี้ชื่อผู้ใช้ (ทางเลือก) ยังไม่ได้รับการยืนยันว่าเป็นที่ยอมรับของเจ้าของที่อยู่อีเมล (ใหม่) อาจมีภาษาที่ไม่เหมาะสมหรือทำให้เข้าใจผิดซึ่งเลือกโดยบุคคลที่ไม่ได้เป็นเจ้าของที่อยู่จริงๆ
try {
$ auth -> login ( $ _POST [ ' email ' ], $ _POST [ ' password ' ]);
echo ' User is logged in ' ;
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Wrong email address ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Wrong password ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Email not verified ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หากคุณต้องการลงชื่อเข้าใช้ด้วยชื่อผู้ใช้ นอกเหนือจากการเข้าสู่ระบบผ่านที่อยู่อีเมลหรือแทนที่ ก็สามารถทำได้เช่นกัน เพียงเรียกเมธอด loginWithUsername
แทนเมธอด login
จากนั้น แทนที่จะจับ InvalidEmailException
ตรวจสอบให้แน่ใจว่าจับทั้ง UnknownUsernameException
และ AmbiguousUsernameException
คุณอาจต้องการอ่านหมายเหตุเกี่ยวกับเอกลักษณ์ของชื่อผู้ใช้ในส่วนที่อธิบายวิธีการลงทะเบียนผู้ใช้ใหม่
แยกตัวเลือกและโทเค็นออกจาก URL ที่ผู้ใช้คลิกในอีเมลยืนยัน
try {
$ auth -> confirmEmail ( $ _GET [ ' selector ' ], $ _GET [ ' token ' ]);
echo ' Email address has been verified ' ;
}
catch ( Delight Auth InvalidSelectorTokenPairException $ e ) {
die ( ' Invalid token ' );
}
catch ( Delight Auth TokenExpiredException $ e ) {
die ( ' Token expired ' );
}
catch ( Delight Auth UserAlreadyExistsException $ e ) {
die ( ' Email address already exists ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หากคุณต้องการให้ผู้ใช้ลงชื่อเข้าใช้โดยอัตโนมัติหลังจากการยืนยันสำเร็จ เพียงโทร confirmEmailAndSignIn
แทน confirmEmail
วิธีอื่นนั้นยังรองรับการเข้าสู่ระบบแบบถาวรผ่านพารามิเตอร์ตัวที่สามที่เป็นตัวเลือก
เมื่อประสบความสำเร็จ ทั้งสองวิธี confirmEmail
และ confirmEmailAndSignIn
จะส่งคืนอาร์เรย์พร้อมที่อยู่อีเมลใหม่ของผู้ใช้ซึ่งเพิ่งได้รับการยืนยันที่ดัชนีหนึ่ง หากการยืนยันเป็นการเปลี่ยนแปลงที่อยู่แทนการยืนยันที่อยู่แบบธรรมดา ที่อยู่อีเมลเก่าของผู้ใช้จะถูกรวมไว้ในอาร์เรย์ที่ดัชนีศูนย์
พารามิเตอร์ตัวที่สามของเมธอด Auth#login
และ Auth#confirmEmailAndSignIn
จะควบคุมว่าการเข้าสู่ระบบจะคงอยู่ด้วยคุกกี้ที่มีอายุการใช้งานยาวนานหรือไม่ ด้วยการเข้าสู่ระบบอย่างต่อเนื่อง ผู้ใช้อาจได้รับการตรวจสอบสิทธิ์เป็นเวลานาน แม้ว่าเซสชันของเบราว์เซอร์จะถูกปิดไปแล้วและคุกกี้ของเซสชันจะหมดอายุก็ตาม โดยทั่วไป คุณจะต้องให้ผู้ใช้เข้าสู่ระบบเป็นเวลาหลายสัปดาห์หรือหลายเดือนด้วยฟีเจอร์นี้ ซึ่งเรียกว่า "จดจำฉัน" หรือ "ให้ฉันอยู่ในระบบต่อไป" ผู้ใช้จำนวนมากจะพบว่าสิ่งนี้สะดวกกว่า แต่อาจมีความปลอดภัยน้อยลงหากปล่อยอุปกรณ์ทิ้งไว้โดยไม่มีใครดูแล
if ( $ _POST [ ' remember ' ] == 1 ) {
// keep logged in for one year
$ rememberDuration = ( int ) ( 60 * 60 * 24 * 365.25 );
}
else {
// do not keep logged in after session ends
$ rememberDuration = null ;
}
// ...
$ auth -> login ( $ _POST [ ' email ' ], $ _POST [ ' password ' ], $ rememberDuration );
// . . .
หากไม่มี การเข้าสู่ระบบแบบถาวรซึ่งเป็นพฤติกรรม เริ่มต้น ผู้ใช้จะยังคงอยู่ในระบบจนกว่าจะปิดเบราว์เซอร์เท่านั้น หรือตราบเท่าที่กำหนดค่าผ่าน session.cookie_lifetime
และ session.gc_maxlifetime
ใน PHP
ละเว้นพารามิเตอร์ที่สามหรือตั้งค่าเป็น null
เพื่อปิดใช้งานคุณลักษณะนี้ มิฉะนั้น คุณอาจถามผู้ใช้ว่าต้องการเปิดใช้งาน "จดจำฉัน" หรือไม่ โดยปกติจะทำโดยใช้ช่องทำเครื่องหมายในส่วนต่อประสานผู้ใช้ของคุณ ใช้อินพุตจากช่องทำเครื่องหมายนั้นเพื่อตัดสินใจระหว่าง null
และระยะเวลาที่กำหนดไว้ล่วงหน้าเป็นวินาทีที่นี่ เช่น 60 * 60 * 24 * 365.25
เป็นเวลาหนึ่งปี
try {
$ auth -> forgotPassword ( $ _POST [ ' email ' ], function ( $ selector , $ token ) {
echo ' Send ' . $ selector . ' and ' . $ token . ' to the user (e.g. via email) ' ;
echo ' For emails, consider using the mail(...) function, Symfony Mailer, Swiftmailer, PHPMailer, etc. ' ;
echo ' For SMS, consider using a third-party service and a compatible SDK ' ;
});
echo ' Request has been generated ' ;
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Invalid email address ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Email not verified ' );
}
catch ( Delight Auth ResetDisabledException $ e ) {
die ( ' Password reset is disabled ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หมายเหตุ: ฟังก์ชันการโทรกลับแบบไม่ระบุชื่อเป็นการปิดตัวลง ดังนั้น นอกเหนือจากพารามิเตอร์ของตัวเองแล้ว มีเพียง superglobals เช่น $_GET
, $_POST
, $_COOKIE
และ $_SERVER
เท่านั้นที่สามารถใช้ได้ภายใน สำหรับตัวแปรอื่นๆ จากขอบเขตหลัก คุณต้องทำให้สำเนาพร้อมใช้งานภายในอย่างชัดเจนโดยการเพิ่มคำสั่ง use
หลังรายการพารามิเตอร์
คุณควรสร้าง URL ด้วยตัวเลือกและโทเค็นและส่งไปยังผู้ใช้ เช่น:
$ url = ' https://www.example.com/reset_password?selector= ' . urlencode ( $ selector ) . ' &token= ' . urlencode ( $ token );
หากอายุการใช้งานเริ่มต้นของคำขอรีเซ็ตรหัสผ่านไม่ได้ผลสำหรับคุณ คุณสามารถใช้พารามิเตอร์ที่สามของ Auth#forgotPassword
เพื่อระบุช่วงเวลาที่กำหนดเองในหน่วยวินาทีหลังจากนั้นคำขอจะหมดอายุ
ในขั้นตอนถัดไปผู้ใช้จะคลิกลิงก์ที่ได้รับ แยกตัวเลือกและโทเค็นออกจาก URL
หากคู่ตัวเลือก/โทเค็นถูกต้อง ให้ผู้ใช้เลือกรหัสผ่านใหม่:
try {
$ auth -> canResetPasswordOrThrow ( $ _GET [ ' selector ' ], $ _GET [ ' token ' ]);
echo ' Put the selector into a "hidden" field (or keep it in the URL) ' ;
echo ' Put the token into a "hidden" field (or keep it in the URL) ' ;
echo ' Ask the user for their new password ' ;
}
catch ( Delight Auth InvalidSelectorTokenPairException $ e ) {
die ( ' Invalid token ' );
}
catch ( Delight Auth TokenExpiredException $ e ) {
die ( ' Token expired ' );
}
catch ( Delight Auth ResetDisabledException $ e ) {
die ( ' Password reset is disabled ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หรือหากคุณไม่ต้องการข้อความแสดงข้อผิดพลาดใดๆ แต่เพียงต้องการตรวจสอบความถูกต้อง คุณสามารถใช้เวอร์ชันที่ง่ายกว่าเล็กน้อย:
if ( $ auth -> canResetPassword ( $ _GET [ ' selector ' ], $ _GET [ ' token ' ])) {
echo ' Put the selector into a "hidden" field (or keep it in the URL) ' ;
echo ' Put the token into a "hidden" field (or keep it in the URL) ' ;
echo ' Ask the user for their new password ' ;
}
ตอนนี้เมื่อคุณมีรหัสผ่านใหม่สำหรับผู้ใช้แล้ว (และยังมีข้อมูลอีกสองชิ้น) คุณสามารถรีเซ็ตรหัสผ่านได้:
try {
$ auth -> resetPassword ( $ _POST [ ' selector ' ], $ _POST [ ' token ' ], $ _POST [ ' password ' ]);
echo ' Password has been reset ' ;
}
catch ( Delight Auth InvalidSelectorTokenPairException $ e ) {
die ( ' Invalid token ' );
}
catch ( Delight Auth TokenExpiredException $ e ) {
die ( ' Token expired ' );
}
catch ( Delight Auth ResetDisabledException $ e ) {
die ( ' Password reset is disabled ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
คุณต้องการให้ผู้ใช้ที่เกี่ยวข้องลงชื่อเข้าใช้โดยอัตโนมัติเมื่อรีเซ็ตรหัสผ่านสำเร็จหรือไม่ เพียงใช้ Auth#resetPasswordAndSignIn
แทน Auth#resetPassword
เพื่อเข้าสู่ระบบผู้ใช้ทันที
หากคุณต้องการ ID ผู้ใช้หรือที่อยู่อีเมล เช่น สำหรับการส่งการแจ้งเตือนว่ารหัสผ่านของพวกเขาถูกรีเซ็ตสำเร็จแล้ว เพียงใช้ค่าที่ส่งคืนของ Auth#resetPassword
ซึ่งเป็นอาร์เรย์ที่ประกอบด้วยสองรายการชื่อ id
และ email
หากผู้ใช้เข้าสู่ระบบอยู่ ผู้ใช้อาจเปลี่ยนรหัสผ่านได้
try {
$ auth -> changePassword ( $ _POST [ ' oldPassword ' ], $ _POST [ ' newPassword ' ]);
echo ' Password has been changed ' ;
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' Not logged in ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password(s) ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
การขอรหัสผ่านปัจจุบันจากผู้ใช้ (และ เก่า เร็วๆ นี้ ) และกำหนดให้มีการตรวจสอบเป็นวิธีที่แนะนำในการจัดการกับการเปลี่ยนรหัสผ่าน นี่แสดงไว้ด้านบน
หากคุณแน่ใจว่าไม่ต้องการการยืนยันดังกล่าว คุณสามารถเรียก changePasswordWithoutOldPassword
แทน changePassword
และปล่อยพารามิเตอร์แรกจากการเรียกเมธอดนั้น (ซึ่งมิฉะนั้นก็จะมีรหัสผ่านเก่า)
ไม่ว่าในกรณีใด หลังจากที่เปลี่ยนรหัสผ่านของผู้ใช้แล้ว คุณควรส่งอีเมลไปยังที่อยู่อีเมลหลักของบัญชีของพวกเขา เพื่อเป็นการแจ้งเตือนนอกกลุ่มเพื่อแจ้งให้เจ้าของบัญชีทราบเกี่ยวกับการเปลี่ยนแปลงที่สำคัญนี้
หากผู้ใช้เข้าสู่ระบบอยู่ ผู้ใช้อาจเปลี่ยนที่อยู่อีเมลของตน
try {
if ( $ auth -> reconfirmPassword ( $ _POST [ ' password ' ])) {
$ auth -> changeEmail ( $ _POST [ ' newEmail ' ], function ( $ selector , $ token ) {
echo ' Send ' . $ selector . ' and ' . $ token . ' to the user (e.g. via email to the *new* address) ' ;
echo ' For emails, consider using the mail(...) function, Symfony Mailer, Swiftmailer, PHPMailer, etc. ' ;
echo ' For SMS, consider using a third-party service and a compatible SDK ' ;
});
echo ' The change will take effect as soon as the new email address has been confirmed ' ;
}
else {
echo ' We can ' t say if the user is who they claim to be ' ;
}
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Invalid email address ' );
}
catch ( Delight Auth UserAlreadyExistsException $ e ) {
die ( ' Email address already exists ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Account not verified ' );
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' Not logged in ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หมายเหตุ: ฟังก์ชันการโทรกลับแบบไม่ระบุชื่อเป็นการปิดตัวลง ดังนั้น นอกเหนือจากพารามิเตอร์ของตัวเองแล้ว มีเพียง superglobals เช่น $_GET
, $_POST
, $_COOKIE
และ $_SERVER
เท่านั้นที่สามารถใช้ได้ภายใน สำหรับตัวแปรอื่นๆ จากขอบเขตหลัก คุณต้องทำให้สำเนาพร้อมใช้งานภายในอย่างชัดเจนโดยการเพิ่มคำสั่ง use
หลังรายการพารามิเตอร์
สำหรับการยืนยันอีเมล คุณควรสร้าง URL ที่มีตัวเลือกและโทเค็น และส่งไปยังผู้ใช้ เช่น:
$ url = ' https://www.example.com/verify_email?selector= ' . urlencode ( $ selector ) . ' &token= ' . urlencode ( $ token );
หมายเหตุ: เมื่อส่งอีเมลถึงผู้ใช้ โปรดทราบว่า ณ จุดนี้ชื่อผู้ใช้ (ทางเลือก) ยังไม่ได้รับการยืนยันว่าเป็นที่ยอมรับของเจ้าของที่อยู่อีเมล (ใหม่) อาจมีภาษาที่ไม่เหมาะสมหรือทำให้เข้าใจผิดซึ่งเลือกโดยบุคคลที่ไม่ได้เป็นเจ้าของที่อยู่จริงๆ
หลังจากมีการร้องขอให้เปลี่ยนที่อยู่อีเมล หรือดีกว่านั้น หลังจากที่ผู้ใช้ยืนยันการเปลี่ยนแปลงแล้ว คุณควรส่งอีเมลไปยังที่อยู่อีเมล เดิม ของบัญชีของพวกเขา เพื่อเป็นการแจ้งเตือนนอกวงเพื่อแจ้งให้เจ้าของบัญชีทราบ การเปลี่ยนแปลงที่สำคัญนี้
หมายเหตุ: การเปลี่ยนแปลงที่อยู่อีเมลของผู้ใช้จะมีผลในเซสชันภายในทันทีตามที่คาดไว้ ในเซสชันอื่นๆ (เช่น บนอุปกรณ์อื่นๆ) การเปลี่ยนแปลงอาจต้องใช้เวลาถึงห้านาทีจึงจะมีผล สิ่งนี้จะเพิ่มประสิทธิภาพและมักจะไม่มีปัญหา หากคุณต้องการเปลี่ยนพฤติกรรมนี้ เพียงลด (หรืออาจเพิ่ม) ค่าที่คุณส่งไปยังตัวสร้าง Auth
เป็นอาร์กิวเมนต์ชื่อ $sessionResyncInterval
หากไม่สามารถส่งคำขอยืนยันก่อนหน้านี้ไปยังผู้ใช้ได้ หรือหากผู้ใช้พลาดคำขอนั้น หรือหากพวกเขาไม่ต้องการรออีกต่อไป คุณสามารถส่งคำขอก่อนหน้านี้อีกครั้งในลักษณะนี้:
try {
$ auth -> resendConfirmationForEmail ( $ _POST [ ' email ' ], function ( $ selector , $ token ) {
echo ' Send ' . $ selector . ' and ' . $ token . ' to the user (e.g. via email) ' ;
echo ' For emails, consider using the mail(...) function, Symfony Mailer, Swiftmailer, PHPMailer, etc. ' ;
echo ' For SMS, consider using a third-party service and a compatible SDK ' ;
});
echo ' The user may now respond to the confirmation request (usually by clicking a link) ' ;
}
catch ( Delight Auth ConfirmationRequestNotFound $ e ) {
die ( ' No earlier request found that could be re-sent ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' There have been too many requests -- try again later ' );
}
หากคุณต้องการระบุผู้ใช้ด้วย ID แทนที่จะระบุด้วยที่อยู่อีเมล ก็สามารถทำได้เช่นกัน:
try {
$ auth -> resendConfirmationForUserId ( $ _POST [ ' userId ' ], function ( $ selector , $ token ) {
echo ' Send ' . $ selector . ' and ' . $ token . ' to the user (e.g. via email) ' ;
echo ' For emails, consider using the mail(...) function, Symfony Mailer, Swiftmailer, PHPMailer, etc. ' ;
echo ' For SMS, consider using a third-party service and a compatible SDK ' ;
});
echo ' The user may now respond to the confirmation request (usually by clicking a link) ' ;
}
catch ( Delight Auth ConfirmationRequestNotFound $ e ) {
die ( ' No earlier request found that could be re-sent ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' There have been too many requests -- try again later ' );
}
หมายเหตุ: ฟังก์ชันการโทรกลับแบบไม่ระบุชื่อเป็นการปิดตัวลง ดังนั้น นอกเหนือจากพารามิเตอร์ของตัวเองแล้ว มีเพียง superglobals เช่น $_GET
, $_POST
, $_COOKIE
และ $_SERVER
เท่านั้นที่อยู่ภายใน สำหรับตัวแปรอื่นๆ จากขอบเขตหลัก คุณจะต้องทำให้สำเนาพร้อมใช้งานภายในอย่างชัดเจนโดยการเพิ่มคำสั่ง use
หลังรายการพารามิเตอร์
โดยปกติ คุณควรสร้าง URL ด้วยตัวเลือกและโทเค็น และส่งให้กับผู้ใช้ เช่น ดังต่อไปนี้:
$ url = ' https://www.example.com/verify_email?selector= ' . urlencode ( $ selector ) . ' &token= ' . urlencode ( $ token );
หมายเหตุ: เมื่อส่งอีเมลถึงผู้ใช้ โปรดทราบว่า ณ จุดนี้ชื่อผู้ใช้ (ทางเลือก) ยังไม่ได้รับการยืนยันว่าเป็นที่ยอมรับของเจ้าของที่อยู่อีเมล (ใหม่) อาจมีภาษาที่ไม่เหมาะสมหรือทำให้เข้าใจผิดซึ่งเลือกโดยบุคคลที่ไม่ได้เป็นเจ้าของที่อยู่จริงๆ
$ auth -> logOut ();
// or
try {
$ auth -> logOutEverywhereElse ();
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' Not logged in ' );
}
// or
try {
$ auth -> logOutEverywhere ();
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' Not logged in ' );
}
นอกจากนี้ หากคุณจัดเก็บข้อมูลที่กำหนดเองไว้ในเซสชันด้วย และหากคุณต้องการให้ลบข้อมูลนั้น คุณสามารถทำลายเซสชันทั้งหมดได้โดยการเรียกวิธีที่สอง:
$ auth -> destroySession ();
หมายเหตุ: การออกจากระบบทั่วโลกจะมีผลในเซสชันภายในเครื่องทันทีตามที่คาดไว้ ในเซสชันอื่นๆ (เช่น บนอุปกรณ์อื่นๆ) การเปลี่ยนแปลงอาจต้องใช้เวลาถึงห้านาทีจึงจะมีผล สิ่งนี้จะเพิ่มประสิทธิภาพและมักจะไม่มีปัญหา หากคุณต้องการเปลี่ยนพฤติกรรมนี้ เพียงลด (หรืออาจเพิ่ม) ค่าที่คุณส่งไปยังตัวสร้าง Auth
เป็นอาร์กิวเมนต์ชื่อ $sessionResyncInterval
if ( $ auth -> isLoggedIn ()) {
echo ' User is signed in ' ;
}
else {
echo ' User is not signed in yet ' ;
}
ชวเลข/นามแฝงสำหรับวิธีนี้คือ $auth->check()
$ id = $ auth -> getUserId ();
หากผู้ใช้ไม่ได้ลงชื่อเข้าใช้อยู่ ระบบจะส่งคืนค่า null
ชวเลข/นามแฝงสำหรับวิธีนี้คือ $auth->id()
$ email = $ auth -> getEmail ();
หากผู้ใช้ไม่ได้ลงชื่อเข้าใช้อยู่ ระบบจะส่งคืนค่า null
$ username = $ auth -> getUsername ();
โปรดจำไว้ว่าชื่อผู้ใช้นั้นเป็นทางเลือก และจะมีเพียงชื่อผู้ใช้หากคุณระบุในระหว่างการลงทะเบียน
หากผู้ใช้ไม่ได้ลงชื่อเข้าใช้อยู่ ระบบจะส่งคืนค่า null
if ( $ auth -> isNormal ()) {
echo ' User is in default state ' ;
}
if ( $ auth -> isArchived ()) {
echo ' User has been archived ' ;
}
if ( $ auth -> isBanned ()) {
echo ' User has been banned ' ;
}
if ( $ auth -> isLocked ()) {
echo ' User has been locked ' ;
}
if ( $ auth -> isPendingReview ()) {
echo ' User is pending review ' ;
}
if ( $ auth -> isSuspended ()) {
echo ' User has been suspended ' ;
}
if ( $ auth -> isRemembered ()) {
echo ' User did not sign in but was logged in through their long-lived cookie ' ;
}
else {
echo ' User signed in manually ' ;
}
หากผู้ใช้ไม่ได้ลงชื่อเข้าใช้อยู่ ระบบจะส่งคืนค่า null
$ ip = $ auth -> getIpAddress ();
เพื่อรักษาความเหมาะสมของไลบรารีนี้สำหรับทุกวัตถุประสงค์ตลอดจนความสามารถในการนำกลับมาใช้ใหม่ได้อย่างสมบูรณ์ ห้องสมุดจึงไม่ได้มาพร้อมกับคอลัมน์รวมกลุ่มเพิ่มเติมสำหรับข้อมูลผู้ใช้ แต่คุณไม่จำเป็นต้องดำเนินการโดยไม่มีข้อมูลผู้ใช้เพิ่มเติม แน่นอน:
ต่อไปนี้คือวิธีใช้ไลบรารีนี้กับตารางของคุณเองสำหรับข้อมูลผู้ใช้แบบกำหนดเองในลักษณะที่สามารถดูแลรักษาและนำกลับมาใช้ใหม่ได้:
เพิ่มตารางฐานข้อมูลที่กำหนดเองจำนวนเท่าใดก็ได้ที่คุณจัดเก็บข้อมูลผู้ใช้ที่กำหนดเอง เช่น ตารางชื่อ profiles
เมื่อใดก็ตามที่คุณเรียกใช้เมธอด register
(ซึ่งส่งคืน ID ผู้ใช้ใหม่) ให้เพิ่มตรรกะของคุณเองหลังจากนั้นเพื่อเติมตารางฐานข้อมูลที่คุณกำหนดเอง
หากคุณต้องการข้อมูลผู้ใช้แบบกำหนดเองเพียงเล็กน้อย คุณก็อาจเรียกคืนข้อมูลดังกล่าวได้ตามต้องการ อย่างไรก็ตาม หากคุณต้องการใช้บ่อยกว่านี้ คุณอาจต้องการมีข้อมูลดังกล่าวในข้อมูลเซสชันของคุณ วิธีการต่อไปนี้คือวิธีที่คุณสามารถโหลดและเข้าถึงข้อมูลของคุณด้วยวิธีที่เชื่อถือได้:
function getUserInfo ( Delight Auth Auth $ auth ) {
if (! $ auth -> isLoggedIn ()) {
return null ;
}
if (! isset ( $ _SESSION [ ' _internal_user_info ' ])) {
// TODO : load your custom user information and assign it to the session variable below
// $ _SESSION [ ' _internal_user_info' ] = ...
}
return $ _SESSION [ ' _internal_user_info ' ];
}
เมื่อใดก็ตามที่คุณต้องการยืนยันตัวตนของผู้ใช้อีกครั้ง เช่น ก่อนที่ผู้ใช้จะได้รับอนุญาตให้ดำเนินการที่ "อันตราย" คุณควรตรวจสอบรหัสผ่านอีกครั้งเพื่อยืนยันว่าพวกเขาเป็นคนที่พวกเขาอ้างว่าเป็นจริง
ตัวอย่างเช่น เมื่อผู้ใช้ถูกจดจำโดยคุกกี้ที่มีอายุยาวนาน และด้วยเหตุนี้ Auth#isRemembered
จึงส่งคืน true
ซึ่งหมายความว่าผู้ใช้อาจไม่ได้ป้อนรหัสผ่านมาระยะหนึ่งแล้ว คุณอาจต้องการยืนยันรหัสผ่านอีกครั้งในกรณีนั้น
try {
if ( $ auth -> reconfirmPassword ( $ _POST [ ' password ' ])) {
echo ' The user really seems to be who they claim to be ' ;
}
else {
echo ' We can ' t say if the user is who they claim to be ' ;
}
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' The user is not signed in ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
ผู้ใช้ทุกคนสามารถมีบทบาทจำนวนเท่าใดก็ได้ ซึ่งคุณสามารถใช้เพื่อดำเนินการอนุญาตและปรับแต่งการควบคุมการเข้าถึงของคุณได้
ผู้ใช้อาจไม่มีบทบาทเลย (ซึ่งทำโดยค่าเริ่มต้น) บทบาทเดียวเท่านั้น หรือบทบาทใด ๆ รวมกันตามอำเภอใจ
if ( $ auth -> hasRole ( Delight Auth Role:: SUPER_MODERATOR )) {
echo ' The user is a super moderator ' ;
}
// or
if ( $ auth -> hasAnyRole ( Delight Auth Role:: DEVELOPER , Delight Auth Role:: MANAGER )) {
echo ' The user is either a developer, or a manager, or both ' ;
}
// or
if ( $ auth -> hasAllRoles ( Delight Auth Role:: DEVELOPER , Delight Auth Role:: MANAGER )) {
echo ' The user is both a developer and a manager ' ;
}
แม้ว่าเมธอด hasRole
จะใช้เพียงบทบาทเดียวเป็นอาร์กิวเมนต์ แต่ทั้งสองเมธอด hasAnyRole
และ hasAllRoles
สามารถรับบทบาทจำนวนเท่าใดก็ได้ที่คุณต้องการตรวจสอบ
หรือคุณสามารถรับรายการบทบาททั้งหมดที่ถูกกำหนดให้กับผู้ใช้:
$ auth -> getRoles ();
Delight Auth Role:: ADMIN ;
Delight Auth Role:: AUTHOR ;
Delight Auth Role:: COLLABORATOR ;
Delight Auth Role:: CONSULTANT ;
Delight Auth Role:: CONSUMER ;
Delight Auth Role:: CONTRIBUTOR ;
Delight Auth Role:: COORDINATOR ;
Delight Auth Role:: CREATOR ;
Delight Auth Role:: DEVELOPER ;
Delight Auth Role:: DIRECTOR ;
Delight Auth Role:: EDITOR ;
Delight Auth Role:: EMPLOYEE ;
Delight Auth Role:: MAINTAINER ;
Delight Auth Role:: MANAGER ;
Delight Auth Role:: MODERATOR ;
Delight Auth Role:: PUBLISHER ;
Delight Auth Role:: REVIEWER ;
Delight Auth Role:: SUBSCRIBER ;
Delight Auth Role:: SUPER_ADMIN ;
Delight Auth Role:: SUPER_EDITOR ;
Delight Auth Role:: SUPER_MODERATOR ;
Delight Auth Role:: TRANSLATOR ;
คุณสามารถใช้บทบาทเหล่านี้และเพิกเฉยต่อบทบาทที่คุณไม่ต้องการได้ รายการด้านบนสามารถเรียกค้นได้โดยทางโปรแกรม ในรูปแบบใดรูปแบบหนึ่งจากสามรูปแบบ:
Delight Auth Role:: getMap ();
// or
Delight Auth Role:: getNames ();
// or
Delight Auth Role:: getValues ();
สิทธิ์ของผู้ใช้แต่ละคนจะถูกเข้ารหัสในลักษณะที่ระบุข้อกำหนดบทบาทตลอดทั้งฐานโค้ดของคุณ หากข้อกำหนดเหล่านั้นได้รับการประเมินด้วยชุดบทบาทของผู้ใช้เฉพาะ ผลที่ได้คือการตรวจสอบสิทธิ์โดยปริยาย
สำหรับโปรเจ็กต์ขนาดใหญ่ มักแนะนำให้คงคำจำกัดความของสิทธิ์ไว้ในที่เดียว จากนั้นคุณไม่ต้องตรวจสอบ บทบาท ในตรรกะทางธุรกิจของคุณ แต่คุณตรวจสอบ สิทธิ์แต่ละรายการ คุณสามารถใช้แนวคิดดังกล่าวได้ดังนี้:
function canEditArticle ( Delight Auth Auth $ auth ) {
return $ auth -> hasAnyRole (
Delight Auth Role:: MODERATOR ,
Delight Auth Role:: SUPER_MODERATOR ,
Delight Auth Role:: ADMIN ,
Delight Auth Role:: SUPER_ADMIN
);
}
// . . .
if ( canEditArticle ( $ auth )) {
echo ' The user can edit articles here ' ;
}
// . . .
if ( canEditArticle ( $ auth )) {
echo ' ... and here ' ;
}
// . . .
if ( canEditArticle ( $ auth )) {
echo ' ... and here ' ;
}
อย่างที่คุณเห็น การอนุญาตว่าผู้ใช้บางรายสามารถแก้ไขบทความได้หรือไม่นั้นจะถูกเก็บไว้ที่ตำแหน่งศูนย์กลาง การใช้งานนี้มีข้อดีที่สำคัญสองประการ:
หากคุณ ต้องการทราบว่า ผู้ใช้รายใดสามารถแก้ไขบทความได้ คุณไม่จำเป็นต้องตรวจสอบตรรกะทางธุรกิจของคุณในที่ต่างๆ แต่คุณต้องดูว่าสิทธิ์เฉพาะเจาะจงถูกกำหนดไว้ที่ใดเท่านั้น และถ้าคุณต้องการ เปลี่ยน ผู้ที่สามารถแก้ไขบทความได้ คุณจะต้องทำสิ่งนี้ในที่เดียวเท่านั้น ไม่ใช่ทั่วทั้งฐานโค้ดของคุณ
แต่สิ่งนี้ยังมาพร้อมกับค่าใช้จ่ายที่มากขึ้นเล็กน้อยเมื่อใช้ข้อจำกัดการเข้าถึงเป็นครั้งแรก ซึ่งอาจคุ้มค่าหรือไม่คุ้มกับโปรเจ็กต์ของคุณ
หากชื่อของบทบาทที่รวมไว้ใช้ไม่ได้สำหรับคุณ คุณสามารถตั้งชื่อแทนบทบาทจำนวนเท่าใดก็ได้โดยใช้ตัวระบุของคุณเอง เช่น:
namespace My Namespace ;
final class MyRole {
const CUSTOMER_SERVICE_AGENT = Delight Auth Role:: REVIEWER ;
const FINANCIAL_DIRECTOR = Delight Auth Role:: COORDINATOR ;
private function __construct () {}
}
ตัวอย่างข้างต้นจะช่วยให้คุณใช้งานได้
My Namespace MyRole:: CUSTOMER_SERVICE_AGENT ;
// and
My Namespace MyRole:: FINANCIAL_DIRECTOR ;
แทน
Delight Auth Role:: REVIEWER ;
// and
Delight Auth Role:: COORDINATOR ;
เพียงจำไว้ว่า อย่า นามแฝงบทบาทที่รวมไว้ เพียงบทบาทเดียว กับ หลาย บทบาทด้วยชื่อที่กำหนดเอง
แม้ว่าการรีเซ็ตรหัสผ่านทางอีเมลเป็นคุณสมบัติที่สะดวกสบายซึ่งผู้ใช้ส่วนใหญ่พบว่ามีประโยชน์เป็นครั้งคราว ความพร้อมใช้งานของคุณสมบัตินี้หมายความว่าบัญชีในบริการของคุณจะมีความปลอดภัยเท่ากับบัญชีอีเมลที่เชื่อมโยงของผู้ใช้เท่านั้น
คุณสามารถให้ความเป็นไปได้แก่ผู้ใช้ที่คำนึงถึงความปลอดภัย (และมีประสบการณ์) เพื่อปิดการใช้งานการรีเซ็ตรหัสผ่านสำหรับบัญชีของพวกเขา (และเปิดใช้งานอีกครั้งในภายหลัง) เพื่อเพิ่มความปลอดภัย:
try {
if ( $ auth -> reconfirmPassword ( $ _POST [ ' password ' ])) {
$ auth -> setPasswordResetEnabled ( $ _POST [ ' enabled ' ] == 1 );
echo ' The setting has been changed ' ;
}
else {
echo ' We can ' t say if the user is who they claim to be ' ;
}
}
catch ( Delight Auth NotLoggedInException $ e ) {
die ( ' The user is not signed in ' );
}
catch ( Delight Auth TooManyRequestsException $ e ) {
die ( ' Too many requests ' );
}
หากต้องการตรวจสอบค่าปัจจุบันของการตั้งค่านี้ ให้ใช้ค่าที่ส่งคืนจาก
$ auth -> isPasswordResetEnabled ();
สำหรับตัวเลือกเริ่มต้นที่ถูกต้องในส่วนติดต่อผู้ใช้ของคุณ คุณไม่จำเป็นต้องตรวจสอบค่านี้เพื่อดูข้อจำกัดของฟีเจอร์ซึ่งจะบังคับใช้โดยอัตโนมัติ
วิธีการทั้งหมดที่จัดทำโดยไลบรารีนี้ได้รับการป้องกัน โดยอัตโนมัติ จากการร้องขอจากไคลเอนต์จำนวนมากเกินไป หากจำเป็น คุณสามารถปิดใช้งานการป้องกันนี้ (ชั่วคราว) ได้โดยใช้พารามิเตอร์ $throttling
ที่ส่งไปยังตัวสร้าง
หากคุณต้องการควบคุมหรือจำกัดอัตราคุณสมบัติหรือวิธีการ ภายนอก เช่น ในโค้ดของคุณเอง คุณสามารถใช้วิธีตัวช่วยในตัวสำหรับการควบคุมปริมาณและการจำกัดอัตรา:
try {
// throttle the specified resource or feature to * 3 * requests per * 60 * seconds
$ auth -> throttle ([ ' my-resource-name ' ], 3 , 60 );
echo ' Do something with the resource or feature ' ;
}
catch ( Delight Auth TooManyRequestsException $ e ) {
// operation cancelled
http_response_code ( 429 );
exit ;
}
หากการปกป้องทรัพยากรหรือคุณลักษณะควรขึ้นอยู่กับคุณลักษณะอื่นเพิ่มเติม เช่น เพื่อติดตามบางสิ่งแยกกันตามที่อยู่ IP เพียงเพิ่มข้อมูลเพิ่มเติมลงในคำอธิบายทรัพยากร เช่น:
[ ' my-resource-name ' , $ _SERVER [ ' REMOTE_ADDR ' ] ]
// instead of
// [ ' my-resource-name' ]
การอนุญาตให้มีกิจกรรมต่อเนื่องสั้นๆ ในระหว่างความต้องการสูงสุดนั้นเป็นไปได้โดยการระบุปัจจัยการระเบิดเป็นอาร์กิวเมนต์ที่สี่ ตัวอย่างเช่น ค่า 5
จะอนุญาตให้มีกิจกรรมเพิ่มขึ้นเป็นห้าเท่าชั่วคราว เมื่อเปรียบเทียบกับระดับที่ยอมรับโดยทั่วไป
ในบางกรณี คุณอาจต้องการ จำลอง การควบคุมปริมาณหรือการจำกัดอัตรา ซึ่งช่วยให้คุณตรวจสอบว่าการดำเนินการจะได้รับอนุญาตหรือไม่โดยไม่ต้องแก้ไขตัวติดตามกิจกรรมจริง ๆ หากต้องการทำเช่นนั้น เพียงส่งค่า true
เป็นอาร์กิวเมนต์ที่ห้า
หมายเหตุ: เมื่อคุณปิดใช้งานการควบคุมปริมาณบนอินสแตนซ์ (โดยใช้พารามิเตอร์ $throttling
ที่ส่งไปยังตัวสร้าง) จะเป็นการปิดทั้งการป้องกันภายในอัตโนมัติและผลกระทบของการเรียก Auth#throttle
ในโค้ดแอปพลิเคชันของคุณเอง เว้นแต่คุณจะตั้งค่า พารามิเตอร์ $force
ที่เป็นทางเลือกให้เป็น true
ในการเรียก Auth#throttle
เฉพาะเจาะจง
อินเทอร์เฟซผู้ดูแลระบบสามารถใช้ได้ผ่าน $auth->admin()
คุณสามารถเรียกวิธีการต่างๆ บนอินเทอร์เฟซนี้ได้ ดังเอกสารด้านล่าง
อย่าลืมใช้การควบคุมการเข้าถึงที่ปลอดภัยก่อนที่จะเปิดเผยการเข้าถึงอินเทอร์เฟซนี้ ตัวอย่างเช่น คุณอาจให้สิทธิ์การเข้าถึงอินเทอร์เฟซนี้แก่ผู้ใช้ที่เข้าสู่ระบบด้วยบทบาทผู้ดูแลระบบเท่านั้น หรือใช้อินเทอร์เฟซในสคริปต์ส่วนตัวเท่านั้น
try {
$ userId = $ auth -> admin ()-> createUser ( $ _POST [ ' email ' ], $ _POST [ ' password ' ], $ _POST [ ' username ' ]);
echo ' We have signed up a new user with the ID ' . $ userId ;
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Invalid email address ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password ' );
}
catch ( Delight Auth UserAlreadyExistsException $ e ) {
die ( ' User already exists ' );
}
ชื่อผู้ใช้ในพารามิเตอร์ที่สามเป็นทางเลือก คุณสามารถส่ง null
ได้หากคุณไม่ต้องการจัดการชื่อผู้ใช้
ในทางกลับกัน หากคุณต้องการบังคับใช้ชื่อผู้ใช้ที่ไม่ซ้ำ เพียงเรียก createUserWithUniqueUsername
แทน createUser
และเตรียมพร้อมที่จะตรวจจับ DuplicateUsernameException
การลบผู้ใช้ตาม ID:
try {
$ auth -> admin ()-> deleteUserById ( $ _POST [ ' id ' ]);
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown ID ' );
}
การลบผู้ใช้ด้วยที่อยู่อีเมล:
try {
$ auth -> admin ()-> deleteUserByEmail ( $ _POST [ ' email ' ]);
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Unknown email address ' );
}
การลบผู้ใช้ด้วยชื่อผู้ใช้:
try {
$ auth -> admin ()-> deleteUserByUsername ( $ _POST [ ' username ' ]);
}
catch ( Delight Auth UnknownUsernameException $ e ) {
die ( ' Unknown username ' );
}
catch ( Delight Auth AmbiguousUsernameException $ e ) {
die ( ' Ambiguous username ' );
}
เมื่อดึงรายชื่อผู้ใช้ทั้งหมด ข้อกำหนดจะแตกต่างกันมากระหว่างโปรเจ็กต์และกรณีการใช้งาน และการปรับแต่งก็เป็นเรื่องปกติ ตัวอย่างเช่น คุณอาจต้องการดึงคอลัมน์ต่างๆ เข้าร่วมตารางที่เกี่ยวข้อง กรองตามเกณฑ์ที่กำหนด เปลี่ยนวิธีการเรียงลำดับผลลัพธ์ (ในทิศทางที่แตกต่างกัน) และจำกัดจำนวนผลลัพธ์ (ในขณะที่ให้ออฟเซ็ต)
ด้วยเหตุนี้การใช้แบบสอบถาม SQL แบบกำหนดเองรายการเดียวจึงง่ายกว่า เริ่มต้นด้วยสิ่งต่อไปนี้:
SELECT id, email, username, status, verified, roles_mask, registered, last_login FROM users;
try {
$ auth -> admin ()-> addRoleForUserById ( $ userId , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown user ID ' );
}
// or
try {
$ auth -> admin ()-> addRoleForUserByEmail ( $ userEmail , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Unknown email address ' );
}
// or
try {
$ auth -> admin ()-> addRoleForUserByUsername ( $ username , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth UnknownUsernameException $ e ) {
die ( ' Unknown username ' );
}
catch ( Delight Auth AmbiguousUsernameException $ e ) {
die ( ' Ambiguous username ' );
}
หมายเหตุ: การเปลี่ยนแปลงชุดบทบาทของผู้ใช้อาจต้องใช้เวลาถึงห้านาทีจึงจะมีผล สิ่งนี้จะเพิ่มประสิทธิภาพและมักจะไม่มีปัญหา หากคุณต้องการเปลี่ยนพฤติกรรมนี้ เพียงลด (หรืออาจเพิ่ม) ค่าที่คุณส่งไปยังตัวสร้าง Auth
เป็นอาร์กิวเมนต์ชื่อ $sessionResyncInterval
try {
$ auth -> admin ()-> removeRoleForUserById ( $ userId , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown user ID ' );
}
// or
try {
$ auth -> admin ()-> removeRoleForUserByEmail ( $ userEmail , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Unknown email address ' );
}
// or
try {
$ auth -> admin ()-> removeRoleForUserByUsername ( $ username , Delight Auth Role:: ADMIN );
}
catch ( Delight Auth UnknownUsernameException $ e ) {
die ( ' Unknown username ' );
}
catch ( Delight Auth AmbiguousUsernameException $ e ) {
die ( ' Ambiguous username ' );
}
หมายเหตุ: การเปลี่ยนแปลงชุดบทบาทของผู้ใช้อาจต้องใช้เวลาถึงห้านาทีจึงจะมีผล สิ่งนี้จะเพิ่มประสิทธิภาพและมักจะไม่มีปัญหา หากคุณต้องการเปลี่ยนพฤติกรรมนี้ เพียงลด (หรืออาจเพิ่ม) ค่าที่คุณส่งไปยังตัวสร้าง Auth
เป็นอาร์กิวเมนต์ชื่อ $sessionResyncInterval
try {
if ( $ auth -> admin ()-> doesUserHaveRole ( $ userId , Delight Auth Role:: ADMIN )) {
echo ' The specified user is an administrator ' ;
}
else {
echo ' The specified user is not an administrator ' ;
}
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown user ID ' );
}
หรือคุณสามารถรับรายการบทบาททั้งหมดที่ถูกกำหนดให้กับผู้ใช้:
$ auth -> admin ()-> getRolesForUserById ( $ userId );
try {
$ auth -> admin ()-> logInAsUserById ( $ _POST [ ' id ' ]);
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown ID ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Email address not verified ' );
}
// or
try {
$ auth -> admin ()-> logInAsUserByEmail ( $ _POST [ ' email ' ]);
}
catch ( Delight Auth InvalidEmailException $ e ) {
die ( ' Unknown email address ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Email address not verified ' );
}
// or
try {
$ auth -> admin ()-> logInAsUserByUsername ( $ _POST [ ' username ' ]);
}
catch ( Delight Auth UnknownUsernameException $ e ) {
die ( ' Unknown username ' );
}
catch ( Delight Auth AmbiguousUsernameException $ e ) {
die ( ' Ambiguous username ' );
}
catch ( Delight Auth EmailNotVerifiedException $ e ) {
die ( ' Email address not verified ' );
}
try {
$ auth -> admin ()-> changePasswordForUserById ( $ _POST [ ' id ' ], $ _POST [ ' newPassword ' ]);
}
catch ( Delight Auth UnknownIdException $ e ) {
die ( ' Unknown ID ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password ' );
}
// or
try {
$ auth -> admin ()-> changePasswordForUserByUsername ( $ _POST [ ' username ' ], $ _POST [ ' newPassword ' ]);
}
catch ( Delight Auth UnknownUsernameException $ e ) {
die ( ' Unknown username ' );
}
catch ( Delight Auth AmbiguousUsernameException $ e ) {
die ( ' Ambiguous username ' );
}
catch ( Delight Auth InvalidPasswordException $ e ) {
die ( ' Invalid password ' );
}
ไลบรารีนี้ใช้คุกกี้สองตัวเพื่อรักษาสถานะบนไคลเอ็นต์: อันแรกซึ่งมีชื่อที่คุณสามารถดึงข้อมูลได้
session_name ();
เป็นคุกกี้เซสชันทั่วไป (บังคับ) คุกกี้ตัวที่สอง (เป็นทางเลือก) ใช้สำหรับการเข้าสู่ระบบอย่างต่อเนื่องเท่านั้น และสามารถเรียกค้นชื่อได้ดังต่อไปนี้:
Delight Auth Auth:: createRememberCookieName ();
คุณสามารถเปลี่ยนชื่อเซสชันคุกกี้ที่ใช้โดยไลบรารีนี้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้ ตามลำดับคำแนะนำ:
ในการกำหนดค่า PHP ( php.ini
) ให้ค้นหาบรรทัดที่มีคำสั่ง session.name
และเปลี่ยนค่าเป็น session_v1
ดังเช่นใน:
session.name = session_v1
โดยเร็วที่สุดในแอปพลิเคชันของคุณและก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้โทร ini_set
เพื่อเปลี่ยน session.name
เป็น session_v1
ดังเช่นใน:
ini_set ( ' session.name ' , ' session_v1 ' );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
โดยเร็วที่สุดในแอปพลิเคชันของคุณและก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้โทร session_name
ด้วยอาร์กิวเมนต์เช่น session_v1
ดังใน:
session_name ( ' session_v1 ' );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
ชื่อของคุกกี้สำหรับการเข้าสู่ระบบแบบถาวรจะเปลี่ยนเช่นกัน – โดยอัตโนมัติ – หลังจากการเปลี่ยนชื่อคุกกี้เซสชันของคุณ
คุณลักษณะ domain
ของคุกกี้จะควบคุมว่าโดเมนใด (และโดเมนย่อยใด) ที่คุกกี้จะใช้งานได้ และที่ใดที่เซสชั่นของผู้ใช้และสถานะการรับรองความถูกต้องจะพร้อมใช้งาน
ค่าเริ่มต้นที่แนะนำคือสตริงว่าง ซึ่งหมายความว่าคุกกี้จะใช้ได้กับโฮสต์ปัจจุบันทุก ประการ เท่านั้น ไม่รวม โดเมนย่อยใดๆ ที่อาจมีอยู่ คุณควรใช้ค่าอื่นเฉพาะเมื่อคุณต้องการแชร์คุกกี้ระหว่างโดเมนย่อยที่ต่างกัน บ่อยครั้ง คุณจะต้องการแบ่งปันคุกกี้ระหว่างโดเมนเปล่าและโดเมนย่อย www
แต่คุณอาจต้องการแบ่งปันคุกกี้ระหว่างโดเมนย่อยชุดอื่นๆ ด้วย
ไม่ว่าคุณจะเลือกชุดโดเมนย่อยใดก็ตาม คุณควรตั้งค่าแอตทริบิวต์ของคุกกี้ให้เป็นชื่อโดเมน ที่เฉพาะเจาะจงที่สุด ซึ่งยังคงรวมโดเมนย่อยที่จำเป็นทั้งหมดของคุณไว้ ตัวอย่างเช่น หากต้องการแชร์คุกกี้ระหว่าง example.com
และ www.example.com
คุณจะต้องตั้งค่าแอตทริบิวต์เป็น example.com
แต่หากคุณต้องการแชร์คุกกี้ระหว่าง sub1.app.example.com
และ sub2.app.example.com
คุณควรตั้งค่าแอตทริบิวต์เป็น app.example.com
ชื่อโดเมนที่ระบุอย่างชัดเจนจะ รวม โดเมนย่อยทั้งหมดที่มีอยู่เสมอ
คุณสามารถเปลี่ยนแอตทริบิวต์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้ ตามลำดับคำแนะนำ:
ในการกำหนดค่า PHP ( php.ini
) ให้ค้นหาบรรทัดที่มีคำสั่ง session.cookie_domain
และเปลี่ยนค่าตามต้องการ เช่น:
session.cookie_domain = example.com
โดยเร็วที่สุดในแอปพลิเคชันของคุณ และก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้เรียก ini_set
เพื่อเปลี่ยนค่าของคำสั่ง session.cookie_domain
ตามต้องการ เช่น:
ini_set ( ' session.cookie_domain ' , ' example.com ' );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
คุณลักษณะ path
ของคุกกี้จะควบคุมว่าไดเร็กทอรี (และไดเร็กทอรีย่อย) ใดที่คุกกี้จะใช้งานได้ และที่ใดที่เซสชั่นของผู้ใช้และสถานะการรับรองความถูกต้องจะพร้อมใช้งาน
ในกรณีส่วนใหญ่ คุณจะต้องทำให้คุกกี้พร้อมใช้งานสำหรับทุกเส้นทาง เช่น ไดเร็กทอรีและไฟล์ใดๆ โดยเริ่มต้นจากไดเร็กทอรีราก นั่นคือสิ่งที่ค่า /
สำหรับแอตทริบิวต์ทำ ซึ่งเป็นค่าเริ่มต้นที่แนะนำเช่นกัน คุณควรเปลี่ยนแอตทริบิวต์นี้เป็นค่าอื่นเท่านั้น เช่น /path/to/subfolder
หากคุณต้องการจำกัดไดเร็กทอรีที่คุกกี้ของคุณจะสามารถใช้ได้ เช่น เพื่อโฮสต์แอปพลิเคชันหลายตัวเคียงข้างกันในไดเร็กทอรีที่แตกต่างกัน ภายใต้ ชื่อโดเมนเดียวกัน
คุณสามารถเปลี่ยนแอตทริบิวต์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้ ตามลำดับคำแนะนำ:
ในการกำหนดค่า PHP ( php.ini
) ให้ค้นหาบรรทัดที่มีคำสั่ง session.cookie_path
และเปลี่ยนค่าตามต้องการ เช่น:
session.cookie_path = /
โดยเร็วที่สุดในแอปพลิเคชันของคุณ และก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้เรียก ini_set
เพื่อเปลี่ยนค่าของคำสั่ง session.cookie_path
ตามต้องการ เช่น:
ini_set ( ' session.cookie_path ' , ' / ' );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
การใช้แอตทริบิวต์ httponly
คุณสามารถควบคุมได้ว่าสคริปต์ฝั่งไคลเอ็นต์ เช่น JavaScript ควรสามารถเข้าถึงคุกกี้ของคุณหรือไม่ ด้วยเหตุผลด้านความปลอดภัย เป็นการดีที่สุดที่จะ ปฏิเสธ การเข้าถึงสคริปต์ไปยังคุกกี้ของคุณ ซึ่งจะช่วยลดความเสียหายที่การโจมตี XSS ที่ประสบความสำเร็จต่อแอปพลิเคชันของคุณสามารถทำได้ เป็นต้น
ดังนั้น คุณควรตั้งค่า httponly
เป็น 1
เสมอ ยกเว้นในกรณีที่พบไม่บ่อยซึ่งคุณจำเป็นต้องเข้าถึงคุกกี้ของคุณจาก JavaScript จริงๆ และไม่พบวิธีแก้ปัญหาที่ดีกว่านี้ ในกรณีดังกล่าว ให้ตั้งค่าแอตทริบิวต์เป็น 0
แต่ต้องคำนึงถึงผลที่ตามมาด้วย
คุณสามารถเปลี่ยนแอตทริบิวต์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้ ตามลำดับคำแนะนำ:
ในการกำหนดค่า PHP ( php.ini
) ให้ค้นหาบรรทัดที่มีคำสั่ง session.cookie_httponly
และเปลี่ยนค่าตามต้องการ เช่น:
session.cookie_httponly = 1
โดยเร็วที่สุดในแอปพลิเคชันของคุณ และก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้เรียก ini_set
เพื่อเปลี่ยนค่าของคำสั่ง session.cookie_httponly
ตามที่คุณต้องการ เช่น:
ini_set ( ' session.cookie_httponly ' , 1 );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
การใช้แอตทริบิวต์ secure
คุณสามารถควบคุมได้ว่าควรส่งคุกกี้ผ่านการเชื่อมต่อ ใดๆ รวมถึง HTTP ธรรมดา หรือควรจะต้องใช้การเชื่อมต่อที่ปลอดภัย เช่น HTTPS (ที่มี SSL/TLS) หรือไม่ สามารถเลือกโหมดเดิม (ปลอดภัยน้อยกว่า) ได้โดยตั้งค่าแอ็ตทริบิวต์เป็น 0
และโหมดหลัง (ปลอดภัยน้อยกว่า) สามารถเลือกได้โดยตั้งค่าแอ็ตทริบิวต์เป็น 1
แน่นอนว่าสิ่งนี้ขึ้นอยู่กับว่าคุณสามารถแสดงหน้าเว็บ ทั้งหมด ผ่าน HTTPS โดยเฉพาะได้หรือไม่ หากทำได้ คุณควรตั้งค่าแอตทริบิวต์เป็น 1
และอาจรวมกับการเปลี่ยนเส้นทาง HTTP ไปยังโปรโตคอลที่ปลอดภัยและ HTTP Strict Transport Security (HSTS) มิฉะนั้น คุณอาจต้องคงการตั้งค่าแอตทริบิวต์เป็น 0
คุณสามารถเปลี่ยนแอตทริบิวต์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้ ตามลำดับคำแนะนำ:
ในการกำหนดค่า PHP ( php.ini
) ให้ค้นหาบรรทัดที่มีคำสั่ง session.cookie_secure
และเปลี่ยนค่าตามต้องการ เช่น:
session.cookie_secure = 1
โดยเร็วที่สุดในแอปพลิเคชันของคุณ และก่อนที่คุณจะสร้างอินสแตนซ์ Auth
ให้เรียก ini_set
เพื่อเปลี่ยนค่าของคำสั่ง session.cookie_secure
ตามต้องการ เช่น:
ini_set ( ' session.cookie_secure ' , 1 );
เพื่อให้ใช้งานได้ session.auto_start
จะต้องตั้งค่าเป็น 0
ในการกำหนดค่า PHP ( php.ini
)
$ length = 24 ;
$ randomStr = Delight Auth Auth:: createRandomString ( $ length );
$ uuid = Delight Auth Auth:: createUuid ();
สำหรับข้อมูลโดยละเอียดเกี่ยวกับวิธีการอ่านและเขียนข้อมูลเซสชันอย่างสะดวกสบาย โปรดดูเอกสารประกอบของไลบรารีเซสชัน ซึ่งรวมไว้ตามค่าเริ่มต้น
รหัสผ่านหรือโทเค็นการรับรองความถูกต้องใดๆ จะถูกแฮชโดยอัตโนมัติโดยใช้ฟังก์ชัน “bcrypt” ซึ่งใช้รหัส “ปักเป้า” และ (ยังคง) ถือว่าเป็นหนึ่งในฟังก์ชันแฮชรหัสผ่านที่แข็งแกร่งที่สุดในปัจจุบัน “bcrypt” ใช้กับการวนซ้ำ 1,024 ครั้ง เช่น ปัจจัย “ต้นทุน” เท่ากับ 10 “เกลือ” แบบสุ่มจะถูกนำไปใช้โดยอัตโนมัติเช่นกัน
คุณสามารถตรวจสอบการกำหนดค่านี้ได้โดยดูที่แฮชใน users
ตารางฐานข้อมูลของคุณ หากการตั้งค่าของคุณข้างต้นเป็นจริง แฮชรหัสผ่านทั้งหมดในตาราง users
ของคุณควรเริ่มต้นด้วยคำนำหน้า $2$10$
, $2a$10$
หรือ $2y$10$
เมื่อมีการเปิดตัวอัลกอริธึมใหม่ (เช่น Argon2) ในอนาคต ไลบรารีนี้จะดูแลการ "อัปเกรด" แฮชรหัสผ่านที่มีอยู่ของคุณโดยอัตโนมัติทุกครั้งที่ผู้ใช้ลงชื่อเข้าใช้หรือเปลี่ยนรหัสผ่าน
การบังคับใช้ความยาวขั้นต่ำสำหรับรหัสผ่านมักเป็นความคิดที่ดี นอกเหนือจากนั้น คุณอาจต้องการค้นหาว่ารหัสผ่านที่เป็นไปได้นั้นอยู่ในบัญชีดำบางรายการซึ่งคุณสามารถจัดการในฐานข้อมูลหรือในไฟล์ได้หรือไม่ เพื่อป้องกันไม่ให้คำในพจนานุกรมหรือรหัสผ่านที่ใช้กันทั่วไปถูกนำมาใช้ในแอปพลิเคชันของคุณ
เพื่อให้เกิดความยืดหยุ่นและความสะดวกในการใช้งานสูงสุด ไลบรารีนี้ได้รับการออกแบบเพื่อ ไม่ ให้มีการตรวจสอบข้อกำหนดรหัสผ่านเพิ่มเติม แต่อนุญาตให้คุณล้อมเช็คของคุณเองเกี่ยวกับการเรียกเมธอดไลบรารีที่เกี่ยวข้องแทน ตัวอย่าง:
function isPasswordAllowed ( $ password ) {
if ( strlen ( $ password ) < 8 ) {
return false ;
}
$ blacklist = [ ' password1 ' , ' 123456 ' , ' qwerty ' ];
if ( in_array ( $ password , $ blacklist )) {
return false ;
}
return true ;
}
if ( isPasswordAllowed ( $ password )) {
$ auth -> register ( $ email , $ password );
}
คุณอาจลองโหลดไลบรารีนี้ก่อน และสร้างอินสแตนซ์ Auth
ก่อน ก่อนที่ จะโหลดไลบรารีอื่น นอกจากนั้น เราคงทำอะไรไม่ได้มากที่นี่
หากคุณต้องการให้ผู้อื่นรวมเว็บไซต์ของคุณไว้ในองค์ประกอบ <frame>
, <iframe>
, <object>
, <embed>
หรือ <applet>
คุณต้องปิดใช้งานการป้องกันการคลิกแจ็คกิ้งเริ่มต้น:
header_remove ( ' X-Frame-Options ' );
ไลบรารีนี้มีข้อยกเว้นสองประเภทเพื่อระบุปัญหา:
AuthException
และคลาสย่อยของมันจะถูกส่งออกไปทุกครั้งที่วิธีการไม่เสร็จสมบูรณ์ คุณควรจับข้อยกเว้นเหล่านี้ เสมอ เนื่องจากมีการตอบสนองข้อผิดพลาดปกติที่คุณต้องตอบสนองAuthError
และคลาสย่อยจะถูกส่งออกไปทุกครั้งที่มีปัญหาภายในหรือติดตั้งไลบรารีไม่ถูกต้อง คุณ ไม่ ควรจับข้อยกเว้นเหล่านี้ ยินดีต้อนรับการมีส่วนร่วมทั้งหมด! หากคุณต้องการมีส่วนร่วมโปรดสร้างปัญหาก่อนเพื่อให้สามารถพูดคุยกับคุณลักษณะปัญหาหรือคำถามของคุณ
โครงการนี้ได้รับใบอนุญาตภายใต้ข้อกำหนดของใบอนุญาต MIT