คุณอาจเคยได้ยิน (หรือแม้แต่พูดกับตัวเอง) ว่า Rails / Ruby มีเวทย์มนตร์มากเกินไป…
- แต่ความคิดนั้นมาจากไหน?
- เวทมนตร์ของ Rails คืออะไรกันแน่?
- แล้วคุณจะทำอย่างไรเพื่อขจัดเวทมนตร์นั้นได้
นี่คือสิ่งที่ฉันคิด :
เมื่อบางอย่างรู้สึกเหมือนมีมนต์ขลัง นั่นก็เพราะมีบางอย่างที่คุณไม่รู้ จึงมีข้อมูลบางส่วนที่ขาดหายไป
ก็เหมือนกลลวง ถ้ารู้เคล็ดลับก็ไม่มีเวทมนตร์ .
ในการพัฒนาซอฟต์แวร์ การรู้เทคนิคนั้นเทียบเท่ากับการมีความเข้าใจว่าสิ่งต่างๆ ทำงานอย่างไร .
มาดูตัวอย่างกัน!
ตัวอย่างนี้เกี่ยวกับ BCrypt
ซึ่งเป็นอัลกอริธึมการแฮชที่ใช้เก็บรหัสผ่านอย่างปลอดภัย มันถูกนำไปใช้ใน Ruby ผ่าน bcrypt
พลอย
นี่คือวิธีใช้ BCrypt
แฮชคำว่า “การทดสอบ”:
require 'bcrypt'BCrypt::Password.create("testing")# "$2a$10$3o.xrISG8fqKfzKqDpgKn.3cwjFV//9C9cZ7MuK5S9sNKFBivB7YG"BCrypt::Password.create("testing")# "$2a$ BFb/e3cWuAIyelcmkfGtE.GTifXHxig4IzVbdZs9C1zSpF/Jr6c3W"BCrypt::Password.create("กำลังทดสอบ")# "$2a$10$Q952BVgM783Y4kPvwvxwC.CS2DWUX6q2jQupreZoP"สังเกตว่าคุณได้รับแฮชที่แตกต่างกันทุกครั้ง แต่ถ้าคุณใช้บางอย่างเช่น MD5 (อย่า!) หรือ SHA1 คุณจะได้รับผลลัพธ์เดียวกันสำหรับสตริงที่กำหนดเสมอ
ทำไม
BCrypt
ประพฤติตัวแตกต่างไปหรือไม่ฉันจะอธิบายสิ่งที่เกิดขึ้นในอีกสักครู่ แต่ก่อนอื่น มาดูว่าคุณเปรียบเทียบ bcrypt สองรายการอย่างไร แฮช อันหนึ่งมาจากฐานข้อมูล &อันหนึ่งมาจากอินพุตของผู้ใช้ (เช่น แบบฟอร์มหรืออะไรทำนองนั้น)
BCrypt::Password.new(@user.hash) ==params[:password]# trueส่วนทางด้านซ้าย (
BCrypt::Password.new
) เป็นBCrypt
ออบเจ็กต์ซึ่งรับแฮชที่เก็บไว้ในฐานข้อมูลเป็นพารามิเตอร์ส่วนทางด้านขวา (
params[:password]
) เป็นรหัสผ่านแบบข้อความธรรมดาที่ผู้ใช้พยายามเข้าสู่ระบบในกรณีนี้ เราถือว่ามีการใช้รหัสผู้ใช้ / รหัสผ่านที่ถูกต้อง
เหตุใดจึงประเมินเป็น
true
?เพื่อให้เข้าใจสิ่งนี้ คุณต้องรู้สองสิ่ง:
- BCrypt ใช้สิ่งที่เรียกว่า “เกลือ” ซึ่งเป็น ค่าสุ่มที่ใช้เพื่อเพิ่มความปลอดภัย เทียบกับแฮชที่คำนวณไว้ล่วงหน้า เกลือจะถูกเก็บไว้ในแฮชเอง
- ใน Ruby หลายๆ อย่างที่ดูเหมือนวากยสัมพันธ์เป็นเพียงเมธอด . นี่เป็นกรณีของโอเปอเรเตอร์ double equals (
==
)รู้แล้วบอกได้เลยว่า
BCrypt
กำหนด==
. ของตัวเอง ซึ่งรู้วิธีดึงค่า “เกลือ” นั้นมาพิจารณาเมื่อเปรียบเทียบรหัสผ่านกล่าวอีกนัยหนึ่ง :
BCrypt#==
รับค่า "เกลือ" จากแฮชที่เก็บไว้จากนั้นแฮชรหัสผ่านแบบข้อความธรรมดา (อินพุตของผู้ใช้) โดยใช้เกลือนี้ เพื่อให้แฮชทั้งสองจะเหมือนกันหากรหัสผ่านถูกต้อง
หากคุณต้อง ดูซอร์สโค้ด มันจะมีลักษณะดังนี้:
def ==(secret) super( BCrypt::Engine.hash_secret(secret, @salt) ) สิ้นสุดจำไว้ว่า
super
จะเรียกวิธีการเดียวกัน (ในกรณีนี้==
) ในชั้นเรียนหลักคลาสหลักของ
BCrypt::Password
คือString
.มันเป็นเรื่องของวิธีการ
สิ่งสำคัญอย่างหนึ่งที่ต้องทำความเข้าใจคือ นอกจากคีย์เวิร์ดสองสามคำและองค์ประกอบทางไวยากรณ์บางส่วน (เช่น วงเล็บ) ทั้งหมดเกี่ยวกับคลาสและเมธอด
หากคุณรู้ว่าคุณกำลังทำงานกับชั้นเรียนใด (ซึ่งคุณสามารถตรวจสอบได้โดยใช้
class
method) คุณจะสามารถทราบได้เสมอว่ามีการดำเนินการ (วิธีการ) ใดบ้างแต่บางครั้งเราก็มีการเรียกใช้เมธอดโดยไม่มีอ็อบเจ็กต์
ซึ่งมักจะหมายถึงวิธีการที่กำหนดไว้ในคลาสปัจจุบัน แต่ก็ไม่เป็นเช่นนั้นเสมอไป
ตัวอย่าง :
ใส่ 123
puts
. อยู่ที่ไหน กำหนด? มาดูกัน:method(:puts).owner# Kernelอีกสิ่งหนึ่งที่อาจสร้างความสับสนคือ metaprogramming เพราะด้วย metaprogramming คุณสามารถสร้าง แก้ไข หรือแม้แต่ลบวิธีการระหว่างการทำงานของโปรแกรม สิ่งเหล่านี้ทำให้โค้ดมีความทึบและคลุมเครือมากขึ้น
คุณลดความสับสนได้ด้วยการรู้ว่าเมตาโปรแกรมมิ่งมีวิธีการใดและทำงานอย่างไร
สรุป
คุณได้เรียนรู้ว่าความเข้าใจอย่างลึกซึ้งเกี่ยวกับวิธีการทำงานของสิ่งต่างๆ สามารถช่วยขจัด "เวทมนตร์" ใดๆ เขียนโค้ดได้ดีขึ้น และทำให้คุณเป็นนักพัฒนาที่ดีขึ้นได้อย่างไร
หากคุณต้องการพัฒนาทักษะ Ruby ลองดูหนังสือ Ruby Deep Dive ของฉัน ซึ่งออกแบบมาเพื่อเชื่อมช่องว่างระหว่างพื้นฐานและแนวคิดขั้นสูง 🙂