Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ไม่มีเวทมนตร์ในทับทิม

คุณอาจเคยได้ยิน (หรือแม้แต่พูดกับตัวเอง) ว่า 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 ?

เพื่อให้เข้าใจสิ่งนี้ คุณต้องรู้สองสิ่ง:

  1. BCrypt ใช้สิ่งที่เรียกว่า “เกลือ” ซึ่งเป็น ค่าสุ่มที่ใช้เพื่อเพิ่มความปลอดภัย เทียบกับแฮชที่คำนวณไว้ล่วงหน้า เกลือจะถูกเก็บไว้ในแฮชเอง
  2. ใน 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 ของฉัน ซึ่งออกแบบมาเพื่อเชื่อมช่องว่างระหว่างพื้นฐานและแนวคิดขั้นสูง 🙂