给API接口增加Nginx+lua签名认证、Lua生成xml时特殊字符导致XML解析异常处理 及 Lua中find的妙用
林戈的IT生涯 2024-07-12 10:07:03 阅读 70
一、给API接口增加Nginx+lua签名认证
一般我们在请求服务器端的接口时都需要进行签名认识,很多时候都是在PHP程序里将参数按照字母排序,然后连接成一个字符串,再加上一串独立密钥最后md5一下做成一个接口的认证,签名的基本原理也就这些东西,不过在PHP程序中做签名有个问题就是,如果需要自己调试接口的时候,每次参数有变化的时候都需要输入正确的sign签名字符串,才能顺利通过测试,而这会造成极大的不方便。
之前在百度的时候,测试都是一个窗口打开着服务器端的错误日志,里面会记录传入的错误sign值和应该正确的sign值。可以想像这是多么麻烦。
使用nginx+lua将签名独立出来就能避免这样的麻烦。比如下面的配置:
<code>#接口服务器负载
upstream api_backends {
server 127.0.0.1:80 weight=100;
server 127.0.0.1:81 weight=100;
keepalive 60;
}
#响应接口请求的location
location /sign/ {
#lua_code_cache off;
#由lua生成
access_by_lua_file /home/wwwroot/sign/sighcheck.lua;
roxy_set_header Host "www.04007.cn";
proxy_pass http://api_backends;
}
签名验证的工作全部交给access_by_lua_file /home/wwwroot/sign/sighcheck.lua;这里来处理,nginx+lua处理速度也会比php快很多,处理完成后可直接在lua脚本中增加设置head头信息:
ngx.req.set_header("signCheck",0/1);
再在PHP程序中读取此信息以判断验证,甚至可以在nginx里直接阻止签名失败的请求,比如L:
location / {
access_by_lua '
local res = ngx.location.capture("/auth")
if res.status
...
end
';
#再请求PHP
}
这样的话,在测试环境中我们只需要修改nginx配置,过滤过签名验证就可以方便地进行测试。
二、Lua生成xml时内容中的特殊字符导致XML解析异常处理
这前线上的XML文件一直正常,某天产品突然过来找到我,XML在浏览器中显示时报错:This page contains the following errors:error on line 1 at column 145975: Encoding error, Below is a rendering of the page up to the first error. 截图如下:
一开始看到这个问题,还真不知道从哪里下手,目测是哪里有什么特殊字符导致的xml显示异常,但返回的内容太多,根本没法找到问题点。然后根据提示的错误,找到bytes在145975这个位置的内容,发现这个位置的内容确实有些异样,发现打印根本打印不出来这块字符(程序原来在处理时已经去掉了ascii码中小于32的字符),后来通过将字符串base64_encode后通过php解出来,显示出来了字符原型。它们是ASCII扩展字符128~255中的几个字符。临时加了对这几个字符的过滤,暂时解决了。但没过多久就发现其它的地方也有这样的问题,但是我在尝试将128-255的字符都删去,如下:
#lua代码示例
if string.byte(u8char) >= 128 and string.byte(u8char) <= 255 then
#如果ascii码是扩展字符,就全部去掉
return
end
但在操作时发现这样过滤,会将整个内容中的所有中文全部过滤掉了,因为中文的第一个字节就在这个范围。看来这种方式太简单粗暴。lua中用string.byte(s, i)取到字符的byte值。比较第一个字节是228-233,而且接下来两个字节都是 128-191,就可以简单认定为中文,找来一个使用lua过滤特殊字符,只保留中文、英文和数字的方法,用了可行。代码如下:
#lua过滤字符内容,只保留中文,英文和数据的方法
function filter_spec_chars(s)
local ss = {}
local k = 1
while true do
if k > #s then break end
local c = string.byte(s,k)
if not c then break end
if c<192 then
if (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) then
table.insert(ss, string.char(c))
end
k = k + 1
elseif c<224 then
k = k + 2
elseif c<240 then
if c>=228 and c<=233 then
local c1 = string.byte(s,k+1)
local c2 = string.byte(s,k+2)
if c1 and c2 then
local a1,a2,a3,a4 = 128,191,128,191
if c == 228 then a1 = 184
elseif c == 233 then a2,a4 = 190,c1 ~= 190 and 191 or 165
end
if c1>=a1 and c1<=a2 and c2>=a3 and c2<=a4 then
table.insert(ss, string.char(c,c1,c2))
end
end
end
k = k + 3
elseif c<248 then
k = k + 4
elseif c<252 then
k = k + 5
elseif c<254 then
k = k + 6
end
end
return table.concat(ss)
end
三、lua中利用find实现像Php里的explode方法一样切开字符串
lua里面的函数库太少了,手册中的字符串函数就只有那么几个,相比于PHP一大堆的函数,真是不好用。但没办法,lua有lua的优点,还是得用起来,今天因为开发需要,要对字符串进行切割,一看手册,竟然没有这么简单常用的方法,找到了一个结合find,sub来进行切割的实现方法。用起来不错。
有时间真想好好整理好一个常用的lua程序库,避免大家都要去花时间找这个那个方法。
最终实现代码如下:
--用到的几个string里的方法以及table中的insert
local find = string.find
local sub = string.sub
local insert = table.insert
--定义explode方法,参数delimeter即为切割符,str为目标符号。为PHP中的参数顺序一致。
function explode(delimeter, str)
local res = {}
--定义初始位置
local start, start_pos, end_pos = 1, 1, 1
--循环查找字符,每次往后移动一个位置
while true do
start_pos, end_pos = find(str, delimeter, start, true)
if not start_pos then
break
end
--找到字符后通过字符切割将内容保存至table
insert(res, sub(str, start, start_pos - 1))
start = end_pos + 1
end
--别忘了循环结束时还有末尾的内容要保存进来
insert(res, sub(str,start))
return res
end
--实例
local char="2013,2014,2015,2016"code>
local t=explode(',', char)
for k,v in pairs(t) do
print(k.. '=>' .. v)
end
运行结果截图:
上一篇: docker download failed after attempts=6:dial tcp IP:Port i/o timeout
下一篇: ubuntu 各版本图形界面和命令行切换快捷键介绍
本文标签
给API接口增加Nginx+lua签名认证、Lua生成xml时特殊字符导致XML解析异常处理 及 Lua中find的妙用
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。