Rails MessageEncryptor 用法

紅寶鐵軌客
Join to follow...
Follow/Unfollow Writer: 紅寶鐵軌客
By following, you’ll receive notifications when this author publishes new articles.
Don't wait! Sign up to follow this writer.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.
寫程式中、折磨中、享受中 ......
884   0  
·
2020/02/03
·
3 mins read


在實務上,常常需要將一些敏感的資料加密保護,特別是跟「使用者」的個資有關資料,網路法規上也越來越多相關的加密要求,很多 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 來比較內容。

 

 

 

 


WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.


Article info

This article is part of:
Categories:
Tags:
Total: 610 words


Share this article:
About the Author

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




Join the discussion now!
Don't wait! Sign up to join the discussion.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.