Rails MessageEncryptor 用法

紅寶鐵軌客
來關注...
關注/停止關注:紅寶鐵軌客
關注有什麼好處?:當作者有新文章發佈時,「思書」就會自動通知您,讓您更容易與作者互動。
現在就加入《思書》,你就可以關注本作者了!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,讓你寫作不再受限,討論更深入真實,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入
寫程式中、折磨中、享受中 ......
878   0  
·
2020/02/03
·
3分鐘


在實務上,常常需要將一些敏感的資料加密保護,特別是跟「使用者」的個資有關資料,網路法規上也越來越多相關的加密要求,很多 Rails 的開發者都是用外加的 Gem,例如:attr-encrypted,我是個能不用 gem 就不用的人,Rails 的 ActiveSupport 內,就有內建很方便的 ActiveSupport MessageEncryptor 加密功能,以下是我實際使用上的心得記錄:

官方文件上有很好的介紹,使用起來也算方便,但是每次使用都要設定一次,參考這篇文章後,最簡單的方法就是建立一個 service class object,檔案就存在這 app/services/encryption_service.rb,記住,如果更改了 class name,檔名必須跟著變動。

class EncryptionService
  KEY = ActiveSupport::KeyGenerator.new(
    ENV.fetch("SECRET_KEY_BASE")
    # 這可以改設在 secrets 裡,用 Rails.application.secrets.xxxx_key 就可以讀取了
  ).generate_key(
    ENV.fetch("ENCRYPTION_SERVICE_SALT"),
    # 如上,也可以改設在 secrets 裡
    ActiveSupport::MessageEncryptor.key_len
  ).freeze

  private_constant :KEY

  delegate :encrypt_and_sign, :decrypt_and_verify, to: :encryptor

  def self.encrypt(value)
    new.encrypt_and_sign(value)
  end

  def self.decrypt(value)
    new.decrypt_and_verify(value)
  end

  private

  def encryptor
    ActiveSupport::MessageEncryptor.new(KEY)
  end
end

有了這個 service class 以後,要用它就直接呼叫:

@user.secret_text_encrypt = EncryptionService.encrypt(params[:secret_text])
secret_text_decrypt = EncryptionService.decrypt(@user.secret_text_encrypt)

很直覺,也很簡單,只是每次都會需要要選擇要加解密的內容,一般來說,需要加解密的資料都會存在資料庫中,我們可以在 ActiveRecord 中的 model 內,直接將這個欄位加上解鎖的 method:

# decrypt share code
def secret_text_decrypt
  begin
    EncryptionService.decrypt(self.secret_text)
  rescue
    # 如果你的資料有些沒 encrypt,就必須要例外處理
    self.secret_text
  end
end

這樣,存在這個 model 內 secret_text 欄位的加密資料,就可以直接以 secret_text_decrypt 來解密讀取,很方便。  為什麼以上的這段碼有例外處理呢?當 MessageEncryptor 嘗試解密一個未經它加密的內容時,就會出現 ActiveSupport::MessageVerifier::InvalidSignature 的例外錯誤,這很容易發生在原來的資料未加密時,如果資料庫是全新的,就不需要做這事了。

使用 MessageEncryptor 時,要注意,同樣相同的內容,每一次加密後的結果,都會是不一樣的,所以當存入資料庫時 ,如果每次都加密,內容都會變動,如果有 callbacks 在追蹤這個內容變化,每次都會觸動它,目前我的做法是每次要存入資料庫時,先解密比較後,確定不同後再存入,這不是一個好方法,如果有更好的方法請分享,也許 Rails 可以加一個 methods 來比較內容。

 

 

 

 


喜歡作者的文章嗎?馬上按「關注」,當作者發佈新文章時,思書™就會 email 通知您。

思書是公開的寫作平台,創新的多筆名寫作方式,能用不同的筆名探索不同的寫作內容,無限寫作創意,如果您喜歡寫作分享,一定要來試試! 《 加入思書》

思書™是自由寫作平台,本文為作者之個人意見。


文章資訊

本文摘自:
分類於:
標籤:
合計:610字


分享這篇文章:
關於作者

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




參與討論!
現在就加入《思書》,馬上參與討論!
《思書》是一個每個人的寫作與論壇平台,特有的隱私管理,用筆名來區隔你討論內容,讓你的討論更深入,而且免費。 趕快來試試!
還未加入《思書》? 現在就登錄! 已經加入《思書》── 登入


×
登入
申請帳號

需要幫助
關於思書

暗黑模式?
字體大小
成人內容未過濾
更改語言版本?