openresty - lua API(4) - 常用组件

2018-08-02 11:21:06

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

ngx.escape_uri

syntax: newstr = ngx.escape_uri(str)

转义uri。

ngx.unescape_uri

syntax: newstr = ngx.unescape_uri(str)

取消转义。

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

syntax: str = ngx.encode_args(table)

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

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

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

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

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

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

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

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

ngx.decode_base64

syntax: newstr = ngx.decode_base64(str)

base64解码,失败返回 nil。

ngx.crc32_short

syntax: intval = ngx.crc32_short(str)

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

ngx.crc32_long

syntax: intval = ngx.crc32_long(str)

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

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

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

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

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

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

syntax: digest = ngx.md5(str)

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

ngx.md5_bin

syntax: digest = ngx.md5_bin(str)

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

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

syntax: digest = ngx.sha1_bin(str)

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

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

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

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

syntax: quoted_value = ngx.quote_sql_str(raw_value)

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

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

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'

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

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'


备注

1.测试环境centos7 64位,openresty 版本为 1.13.6.2。
2..原文地址http://www.freecls.com/a/2712/f2


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。