-- Some variable declarations.
local cookie = ngx.var.cookie_MyToken
local hmac = ""
local timestamp = ""
local timestamp_time = 0
-- Check that the cookie exists.
if cookie == nil or cookie:find(":") == nil then
-- Internally rewrite the URL so that we serve
-- /auth/ if there's no cookie.
ngx.exec("/auth/")
else
-- If there's a cookie, split off the HMAC signature
-- and timestamp.
local divider = cookie:find(":")
hmac = cookie:sub(divider+1)
timestamp = cookie:sub(0, divider-1)
end
-- Verify that the signature is valid.
if hmac_sha1("some very secret string", timestamp) ~= hmac or tonumber(timestamp) < os.time() then
-- If invalid, send to /auth/ again.
ngx.exec("/auth/")
end
上面的代码可以直接运行。我们用一些明文来签名(这种情况下用的是一个时间戳,当然你可以用任何你想用的),之后我们用密文生成HMAC(哈希信息认证码),然后一个签名就生成了,这样用户就不能篡改为无效信息了。
function compare_strings(str1, str2)
-- Constant-time string comparison function.
local same = true
for i = 1, #str1 do
-- If the two strings' lengths are different, sub()
-- will just return nil for the remaining length.
c1 = str1:sub(i,i)
c2 = str2:sub(i,i)
if c1 ~= c2 then
same = false
end
end
return same
end
我已经在函数上应用了时间来区分,如我所知,这是一个在恒定时间下的等值字符串。不同长度的字符串会稍稍改变时间,也许是因为子过程sub应用了一个不同 的分支而导致的。而且,c1~=c2分支显然不是恒定时间的,但是在实际中,它相当接近恒定,所以于我们的例子不会有影响。我更倾向于使用XOR操作,从 而确定两个字符串的XOR结果是否为0, 不过Lua似乎不包括二进制位的XOR操作。如果我在这个判断上有误,对于任何纠正我都很感激。