摘要:通過查看 resty.aes 源代碼,我們知道它是通過 ffi 調用 OpenSSL 來實現相關功能的,所以我們只要照貓畫虎擴展 resty.aes 即可,不過不要修改 resty.aes 源代碼,否則日後的升級會變得麻煩,最好是新建一個模塊,比如本例中的 resty.aes_with_padding:。因爲 Lua 本身並沒有繼承之類的語法,所以我們不能通過 OOP 的套路來擴展模塊,不過實際上對於 Lua 來說,擴展一個模塊有更簡單的方法,下面我們以 lua-resty-string 模塊中的 aes 加解密功能爲例子來說明一下。

因爲 Lua 本身並沒有繼承之類的語法,所以我們不能通過 OOP 的套路來擴展模塊,不過實際上對於 Lua 來說,擴展一個模塊有更簡單的方法,下面我們以 lua-resty-string 模塊中的 aes 加解密功能爲例子來說明一下。

在 aes 加解密的過程中,有一個「填充」的過程,相關技術細節可以參考我以前寫的「聊聊AES」,當然,不懂也沒關係,你只要知道目前的 resty.aes 不支持配置填充的功能即可,因爲 OpenSSL 缺省是激活了填充的,所以一旦我們需要自定義填充方法,那麼就需要關閉缺省的填充行爲,此時 resty.aes 無能爲力。

通過查看 resty.aes 源代碼,我們知道它是通過 ffi 調用 OpenSSL 來實現相關功能的,所以我們只要照貓畫虎擴展 resty.aes 即可,不過不要修改 resty.aes 源代碼,否則日後的升級會變得麻煩,最好是新建一個模塊,比如本例中的 resty.aes_with_padding:

local aes = require "resty.aes"
local ffi = require "ffi"

local C = ffi.C

ffi.cdef[[
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int padding);
]]

function aes.set_padding(self, padding)
    local encrypt_ctx, decrypt_ctx = self._encrypt_ctx, self._decrypt_ctx

    if encrypt_ctx == nil or decrypt_ctx == nil then
        return nil, "not initialized"
    end

    C.EVP_CIPHER_CTX_set_padding(encrypt_ctx, padding)
    C.EVP_CIPHER_CTX_set_padding(decrypt_ctx, padding)

    return 1
end

return aes

實際使用的時候,把原本調用 resty.aes 的地方改成 resty.aes_with_padding,然後代碼裏通過調用新創建的 set_padding 方法來控制開啓還是關閉填充。

怎麼樣,擴展一個OpenResty模塊和把大象放冰箱一樣簡單吧,總共分三步:1)創建一個新模塊;2)引入要擴展的原模塊;3)直接給原模塊附加新方法。

搞定!

相關文章