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

揭開 Ruby 真相:沒有隱藏魔法 只有透明的代碼

你可能聽過(甚至自己說過)Rails / Ruby 有太多 magic……

  • 這個想法從何而來?
  • Rails magic 到底是什麼?
  • 你能做什麼來消除這種 magic?

這是我的看法:

當某事感覺像 magic 時,是因為有你不知道的事,有些資訊缺失。

這就像魔術表演,如果你知道把戲就沒有 magic 了。

揭開 Ruby 真相:沒有隱藏魔法 只有透明的代碼

在軟體開發中,知道把戲等同於擁有 對事物真實運作方式的理解。

來看個例子!

這個例子關於 BCrypt,一種用於安全儲存密碼的雜湊演算法。它在 Ruby 中透過 bcrypt gem 實現。

這裡展示如何用 BCrypt 雜湊 "testing":

require 'bcrypt' BCrypt::Password.create("testing") # "$2a$10$3o.xrISG8fqKfzKqDpgKn.3cwjFV//9C9cZ7MuK5S9sNKFBivB7YG" BCrypt::Password.create("testing") # "$2a$10$BFb/e3cWuAIyelcmkfGtE.GTifXHxig4IzVbdZs9C1zSpF/Jr6c3W" BCrypt::Password.create("testing") # "$2a$10$Q952BVgM783Y4kPvwvxwC.CS2DWUX9jQuDoE6q2R041kQY0ZWPnSe" 

注意每次都得到不同的雜湊,但如果用 MD5(別用!)或 SHA1,給定字串總會得到相同輸出。

為什麼 BCrypt 行為不同?

我馬上解釋,但先看看如何比較兩個 bcrypt 雜湊,一個來自資料庫,一個來自使用者輸入(如表單)。

BCrypt::Password.new(@user.hash) == params[:password] # true 

左邊(BCrypt::Password.new)是 BCrypt 物件,接收資料庫儲存的雜湊作為參數。

右邊(params[:password])是使用者嘗試登入的明文密碼。

這裡假設使用正確的使用者/密碼組合。

為什麼這評估為 true?

要理解這點,你需要知道兩件事:

  1. BCrypt 使用所謂的「salt」(鹽),這是 用於增加安全性 對抗預計算雜湊的隨機值。Salt 儲存在雜湊本身裡。
  2. 在 Ruby 中 許多看起來像語法的東西其實只是方法。雙等號運算子(==)就是這種情況。

知道這點,我可以告訴你 BCrypt 定義了自己的 == 方法,知道如何提取那個「salt」值,以便在比較密碼時考慮它。

換句話說:

BCrypt#== 從儲存的雜湊取出「salt」值。

然後用這個 salt 雜湊明文密碼(使用者輸入),這樣如果密碼有效,兩個雜湊就會相同。

如果你 看原始碼 它看起來會像這樣:

def ==(secret) super( BCrypt::Engine.hash_secret(secret, @salt) ) end 

記住 super 會在父類別上呼叫同樣的方法(這裡是 ==)。

BCrypt::Password 的父類別是 String。

一切關乎方法

一件重要的事是理解除了少數關鍵字和幾個語法元素(如括號),一切都是關於類別和方法。

如果你知道你在用什麼類別(用 class 方法檢查),你總能知道有哪些操作(方法)可用。

但有時我們只有沒有物件的方法呼叫。

這通常意味著方法定義在當前類別,但不總是如此。

例子:

puts 123 

puts 定義在哪?來找出來:

method(:puts).owner # Kernel 

另一件可能令人困惑的事是 metaprogramming,因為有了 metaprogramming 你可以在程式執行時建立、修改甚至移除方法。這些讓代碼更不透明、更晦澀。

你可以透過了解有哪些 metaprogramming 方法可用及其運作方式來減少困惑。

總結

你學到了深入理解事物運作方式如何幫助你消除任何「magic」、寫出更好的代碼、成為更好的開發者。

如果你想提升 Ruby 技能,看看我的書《Ruby Deep Dive》,專為填補基礎與進階概念之間的鴻溝而設計 🙂