摘自:http://www.daileinote.com/computer/openresty/09

下面列出 lua-nginx-module 模块内置的一些组件。

ngx.escape_uri

1
syntax: newstr = ngx.escape_uri(str)

转义uri。

ngx.unescape_uri

1
syntax: newstr = ngx.unescape_uri(str)

取消转义。

1
2
3
4
5
6
7
8
9
10
location = /test {
content_by_lua_block {
ngx.say(ngx.escape_uri("http://www.freecls.com?name=freecls&age=28"))
ngx.say(ngx.unescape_uri("http%3A%2F%2Fwww.freecls.com%3Fname%3Dfreecls%26age%3D28"))

}
}
[root@192 ~]# curl localhost/test
http%3A%2F%2Fwww.freecls.com%3Fname%3Dfreecls%26age%3D28
http://www.freecls.com?name=freecls&age=28

ngx.encode_args

1
syntax: str = ngx.encode_args(table)

encode Lua表格为uri字符串参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
location = /test {
content_by_lua_block {
ngx.say( ngx.encode_args({foo = 3, ["b r"] = "hello world"}) )
ngx.say( ngx.encode_args({baz = {32, "hello"}}) )

ngx.say( ngx.encode_args({a = true, b = 1, c = false, d = nil}) )
ngx.say( ngx.encode_args({baz = {32, "hello"}}) )
}
}
[root@192 ~]# curl localhost/test
foo=3&b+r=hello+world
baz=32&baz=hello
a&b=1
baz=32&baz=hello

ngx.decode_args

1
syntax: table, err = ngx.decode_args(str, max_args?)

decode 已经被编码的 uri 参数到表格,超过 max_args(默认为100) 指定的参数个数,err为 "truncated",max_args 设置为 0 代表不限制。

1
2
3
4
5
6
7
8
9
10
11
location = /test {
content_by_lua_block {
local args,err = ngx.decode_args("foo=3&b+r=hello+world")
for k,v in pairs(args) do
ngx.say(k, ":",v)
end
}
}
[root@192 ~]# curl localhost/test
b r:hello world
foo:3

ngx.encode_base64

1
syntax: newstr = ngx.encode_base64(str, no_padding?)

base64编码,no_padding 默认为 fasle,意思是要补全。

1
2
ngx.encode_base64("slfjl^&*kdsjkf")        --c2xmamxeJiprZHNqa2Y=
ngx.encode_base64("slfjl^&*kdsjkf", true) --c2xmamxeJiprZHNqa2Y

ngx.decode_base64

1
syntax: newstr = ngx.decode_base64(str)

base64解码,失败返回 nil。

ngx.crc32_short

1
syntax: intval = ngx.crc32_short(str)

生成 crc-32 摘要,str 长度偏短的时候效果更佳,长度小于 30-60字节。内部调用的是 nginx ngx_crc32_short 函数。

ngx.crc32_long

1
syntax: intval = ngx.crc32_long(str)

生成 crc-32 摘要,str 长度偏长的时候效果更佳,长度最好大于 30-60字节。内部调用的是 nginx ngx_crc32_short 函数。

1
2
3
4
5
6
7
8
9
location = /test {
content_by_lua_block {
ngx.say(ngx.crc32_short("123456789"))
ngx.say(ngx.crc32_long("123456789"))
}
}
[root@192 ~]# curl localhost/test
3421780262
3421780262

ngx.hmac_sha1

1
syntax: digest = ngx.hmac_sha1(secret_key, str)

利用 secret_key 计算字符串 str 的 HMAC-SHA1 摘要,该摘要为原生的二进制,最好配置 base64 编码。

需要 openssl 库支持,编译的时候带上 --with-http_ssl_module。

1
2
3
4
5
6
7
8
location = /test {
content_by_lua_block {
local b = ngx.hmac_sha1("i am key", "i am str")
ngx.say(ngx.encode_base64(b))
}
}
[root@192 ~]# curl localhost/test
SRq/4jXNjh5+wk020o23knh4wls=

ngx.md5

1
syntax: digest = ngx.md5(str)

计算 str 的md5值,以16进制表示。

ngx.md5_bin

1
syntax: digest = ngx.md5_bin(str)

计算 str 的md5值,以二进制表示。

1
2
3
4
5
6
7
8
9
10
11
location = /test {
content_by_lua_block {
ngx.say(ngx.md5("hello"))
ngx.say(ngx.md5_bin("hello"))
}
}
[root@192 ~]# curl localhost/test
5d41402abc4b2a76b9719d911017c592
]A@*¼K*v¹qŒ
[root@192 ~]# echo -n 'hello' | md5sum
5d41402abc4b2a76b9719d911017c592 -

ngx.sha1_bin

1
syntax: digest = ngx.sha1_bin(str)

返回str的二进制形式的sha-1摘要。

需要 openssl 库支持,编译的时候带上 --with-http_ssl_module。

下面利用 resty.string 库来转化为16进制。

1
2
3
4
5
6
7
8
9
10
11
12
location = /test {
content_by_lua_block {
local str = require "resty.string"
local sha1b = ngx.sha1_bin("hello")
ngx.say(str.to_hex(sha1b))
}
}
[root@192 ~]# curl localhost/test
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

[root@192 ~]# echo -n 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d -

ngx.quote_sql_str

1
syntax: quoted_value = ngx.quote_sql_str(raw_value)

用来防止 sql 注入,转义内部单双引号,并在开头结尾加上单引号。

下面这个例子有严重的注入风险。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location = /test {
content_by_lua_block {
local args = ngx.req.get_uri_args()

local str = "select * from user where name = "
local res = str.."'"..args.name.."'"

ngx.say(res)
}
}
#正常
curl localhost/test?name=freecls

#select * from user where name = 'freecls'
#注入
curl "localhost/test?name=freecls' or '1'='1"

#select * from user where name = 'freecls' or '1'='1'

下面我们利用该函数来转义引号。

1
2
3
4
5
6
7
8
9
10
11
12
13
location = /test {
content_by_lua_block {
local args = ngx.req.get_uri_args()
args.name = ngx.quote_sql_str(args.name)

local str = "select * from user where name = "
local res = str..args.name

ngx.say(res)
}
}
[root@192 ~]# curl "localhost/test?name=freecls' or '1'='1"
select * from user where name = 'freecls\' or \'1\'=\'1'