lua 替换lua 字符串替换 gsub中的加号

模式匹配函数在string库中功能最强大的函数是:string.find(字符串查找)string.gsub(全局字符串替换)string.gfind(全局字符串查找)string.gmatch(返回查找到字符串的迭代器)这些函数都是基于模式匹配的。与其他脚本语言不同的是,Lua并不使用POSIX规范的正则表达式[4](也写作regexp)来进行模式匹配。主要的原因出于程序大小方面的考虑:实现一个典型的符合POSIX标准的regexp大概需要4000行代码,这比整个Lua标准库加在一起都大。权衡之下,Lua中的模式匹配的实现只用了500行代码,当然这意味着不可能实现POSIX所规范的所有更能。然而,Lua中的模式匹配功能是很强大的,并且包含了一些使用标准POSIX模式匹配不容易实现的功能。
string.gmatch(str, pattern)&&&&&&这是一个返回迭代器的函数. 实际的用例如下:
s = "hello world from Lua"for w in string.gmatch(s, "%a+") do print(w)end
这里是一个捕获并将配对字符分别存到不同变量的例子:
t = {}s = "from=world, to=Lua"for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k]=vendfor k, v in pairs(t) do print(k, v)endstring.gsub(str, pattern, repl, n)
string.gsub()函数根据给定的配对表达式对源字符串str进行配对, 同时返回源字符串的一个副本, 该副本中成功配对的所有子字符串都将被替换. 函数还将返回成功配对的次数.实际的替换行为由repl参数的类型决定:
当repl为字符串时, 所有成功配对的子字符串均会被替换成指定的repl字串.当repl为table时, 对每个成功配对的子字符串, 函数均会试图寻找以其为key值的table中的元素, 并返回该元素. 如果该配对包含任何捕获信息, 则以编号为1号的捕获作为key值进行查找.当repl为函数时, 每个成功配对的子字符串均会作为参数被传入到该函数中去.在repl是table或函数时, 如果该table或函数返回了字串或数字的值, 这个值依然会被用于替换副本字串中的配对子字串. 如果该table/函数返回的值为空, 将不发生替换.
n参数可选, 当它被指定时, string.gsub()函数只对源字符串中的前n个成功配对的成员进行操作.
以下是几个例子:
& print(string.gsub("hello world", "(%w+)", "%1 %1"))hello hello world world 2
& print(string.gsub("hello Lua", "(%w+)%s*(%w+)", "%2 %1"))Lua hello 1
& string.gsub("hello world", "%w+", print)hello world 2
& lookupTable = {["hello"] = "hola", ["world"] = "mundo"}& print(string.gsub("hello world", "(%w+)", lookupTable))hola mundo 2
string.match(str, pattern, init)
string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1.
在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil.
string.match("abcdaef", "a")-& astring.reverse(str)返回一个字符串的倒序排列string.reverse("abcde")-&edcbastring.dump(function)返回指定函数的二进制代码(函数必须是一个Lua函数,并且没有上值)string.find(str, pattern, init, plain) string.find的基本应用就是用来在目标串(subject string)内搜索匹配指定的模式的串。函数如果找到匹配的串返回他的位置,否则返回nil.最简单的模式就是一个单词,仅仅匹配单词本身。比如,模式'hello'仅仅匹配目标串中的"hello"。当查找到模式的时候,函数返回两个值:匹配串开始索引和结束索引。s = "hello world"string.find(s, "hello")&&&&--& 1&&& 5string.find(s, "world")&&& --& 7&&& 11string.find(s, "l")&&&&&&&&--& 3&&& 3string.find(s, "lll")&&&&& --& nilstring.find函数第三个参数是可选的:标示目标串中搜索的起始位置。当我们想查找目标串中所有匹配的子串的时候,这个选项非常有用。我们可以不断的循环搜索,每一次从前一次匹配的结束位置开始。下面看一个例子,下面的代码用一个字符串中所有的新行构造一个表:local t = {}&&&&& -- 存放回车符的位置local i = 0while true do&&& i = string.find(s, "\n", i+1)& --&查找下一行&&& if i == nil then break end&&& table.insert(t, i)endstring.sub(str,sPos,ePos)string.gsub的功能是截取字符串,他从指定起始位置截取一个字符串。string.sub可以利用string.find返回的值截取匹配的子串。对简单模式而言,匹配的就是其本身s = "hello world"local i, j = string.find(s, "hello")&&&&--& 1&&& 5string.sub(s, i, j)&&&&&&& --& hellostring.gsub(str, sourcestr, desstr)string.gsub的基本作用是用来查找匹配模式的串,并将使用替换串其替换掉:string.gsub函数有三个参数:目标串,模式串,替换串。s = string.gsub("Lua is cute", "cute", "great")print(s)&&&&& --& Lua is greats = string.gsub("all lii", "l", "x")print(s)&&&&& --& axx xiis = string.gsub("Lua is great", "perl", "tcl")print(s)&&&&& --& Lua is great第四个参数是可选的,用来限制替换的范围:s = string.gsub("all lii", "l", "x", 1)print(s)&&&&&&&&& --& axl liis = string.gsub("all lii", "l", "x", 2)print(s)&&&&&&&&& --& axx liistring.gsub的第二个返回值表示他进行替换操作的次数。例如,下面代码涌来计算一个字符串中空格出现的次数:_, count = string.gsub(str, " ", " ")(注意,_ 只是一个哑元变量)模式你还可以在模式串中使用字符类。字符类指可以匹配一个特定字符集合内任何字符的模式项。比如,字符类%d匹配任意数字。所以你可以使用模式串'%d%d/%d%d/%d%d%d%d'搜索dd/mm/yyyy格式的日期:s = "Deadline is 30/05/1999, firm"date = "%d%d/%d%d/%d%d%d%d"print(string.sub(s, string.find(s, date)))& & --& 30/05/1999下面的表列出了Lua支持的所有字符类:
单个字符(除^$()%.[]*+-?外): 与该字符自身配对.(点): 与任何字符配对%a: 与任何字母配对%c: 与任何控制符配对(例如\n)%d: 与任何数字配对%l: 与任何小写字母配对%p: 与任何标点(punctuation)配对%s: 与空白字符配对%u: 与任何大写字母配对%w: 与任何字母/数字配对%x: 与任何十六进制数配对%z: 与任何代表0的字符配对%x(此处x是非字母非数字字符): 与字符x配对. 主要用来处理表达式中有功能的字符(^$()%.[]*+-?)的配对问题, 例如%%与%配对[数个字符类]:&与任何[]中包含的字符类配对. 例如[%w_]与任何字母/数字, 或下划线符号(_)配对[^数个字符类]: 与任何不包含在[]中的字符类配对. 例如[^%s]与任何非空白字符配对
当上述的字符类用大写书写时, 表示与非此字符类的任何字符配对. 例如, %S表示与任何非空白字符配对.例如,'%A'非字母的字符print(string.gsub("hello, up-down!", "%A", "."))& & --& hello..up.down. 4(数字4不是字符串结果的一部分,他是gsub返回的第二个结果,代表发生替换的次数。下面其他的关于打印gsub结果的例子中将会忽略这个数值。)在模式匹配中有一些特殊字符,他们有特殊的意义,Lua中的特殊字符如下:( ) . % + - * ? [ ^ $'%' 用作特殊字符的转义字符,因此 '%.' 匹配点;'%%' 匹配字符 '%'。转义字符 '%'不仅可以用来转义特殊字符,还可以用于所有的非字母的字符。当对一个字符有疑问的时候,为安全起见请使用转义字符转义他。对Lua而言,模式串就是普通的字符串。他们和其他的字符串没有区别,也不会受到特殊对待。只有他们被用作模式串用于函数的时候,'%' 才作为转义字符。所以,如果你需要在一个模式串内放置引号的话,你必须使用在其他的字符串中放置引号的方法来处理,使用 '\' 转义引号,'\' 是Lua的转义符。你可以使用方括号将字符类或者字符括起来创建自己的字符类(译者:Lua称之为char-set,就是指传统正则表达式概念中的括号表达式)。比如,'[%w_]' 将匹配字母数字和下划线,'[01]' 匹配二进制数字,'[%[%]]' 匹配一对方括号。下面的例子统计文本中元音字母出现的次数:_, nvow = string.gsub(text, "[AEIOUaeiou]", "")在char-set中可以使用范围表示字符的集合,第一个字符和最后一个字符之间用连字符连接表示这两个字符之间范围内的字符集合。大部分的常用字符范围都已经预定义好了,所以一般你不需要自己定义字符的集合。比如,'%d' 表示 '[0-9]';'%x' 表示 '[0-9a-fA-F]'。然而,如果你想查找八进制数,你可能更喜欢使用 '[0-7]' 而不是 '[]'。你可以在字符集(char-set)的开始处使用 '^' 表示其补集:'[^0-7]' 匹配任何不是八进制数字的字符;'[^\n]' 匹配任何非换行符户的字符。记住,可以使用大写的字符类表示其补集:'%S' 比 '[^%s]' 要简短些。Lua的字符类依赖于本地环境,所以 '[a-z]' 可能与 '%l' 表示的字符集不同。在一般情况下,后者包括 'ç' 和 'ã',而前者没有。应该尽可能的使用后者来表示字母,除非出于某些特殊考虑,因为后者更简单、方便、更高效。可以使用修饰符来修饰模式增强模式的表达能力,Lua中的模式修饰符有四个:+& & & 匹配前一字符1次或多次*& & & 匹配前一字符0次或多次-& & & 匹配前一字符0次或多次?& & & 匹配前一字符0次或1次'+',匹配一个或多个字符,总是进行最长的匹配。比如,模式串 '%a+' 匹配一个或多个字母或者一个单词:print(string.gsub("one, and three", "%a+", "word"))& & --& word, word word'%d+' 匹配一个或多个数字(整数):i, j = string.find("the number 1298 is even", "%d+")print(i,j)& & --& 12& 15'*' 与 '+' 类似,但是他匹配一个字符0次或多次出现.一个典型的应用是匹配空白。比如,为了匹配一对圆括号()或者括号之间的空白,可以使用 '%(%s*%)'。( '%s*' 用来匹配0个或多个空白。由于圆括号在模式中有特殊的含义,所以我们必须使用 '%' 转义他。)再看一个例子,'[_%a][_%w]*' 匹配Lua程序中的标示符:字母或者下划线开头的字母下划线数字序列。'-' 与 '*' 一样,都匹配一个字符的0次或多次出现,但是他进行的是最短匹配。某些时候这两个用起来没有区别,但有些时候结果将截然不同。比如,如果你使用模式 '[_%a][_%w]-' 来查找标示符,你将只能找到第一个字母,因为 '[_%w]-' 永远匹配空。另一方面,假定你想查找C程序中的注释,很多人可能使用 '/%*.*%*/'(也就是说 "/*" 后面跟着任意多个字符,然后跟着 "*/" )。然而,由于 '.*' 进行的是最长匹配,这个模式将匹配程序中第一个 "/*" 和最后一个 "*/" 之间所有部分:test = " /* x */ /* y */"print(string.gsub(test, "/%*.*%*/", "&COMMENT&"))& & --& &COMMENT&然而模式 '.-' 进行的是最短匹配,她会匹配 "/*" 开始到第一个 "*/" 之前的部分:test = " /* x */ /* y */"print(string.gsub(test, "/%*.-%*/", "&COMMENT&"))& & --& &COMMENT& &COMMENT&'?' 匹配一个字符0次或1次。举个例子,假定我们想在一段文本内查找一个整数,整数可能带有正负号。模式 '[+-]?%d+' 符合我们的要求,它可以匹配像 "-12"、"23" 和 "+1009" 等数字。'[+-]' 是一个匹配 '+' 或者 '-' 的字符类;接下来的 '?' 意思是匹配前面的字符类0次或者1次。与其他系统的模式不同的是,Lua中的修饰符不能用字符类;不能将模式分组然后使用修饰符作用这个分组。比如,没有一个模式可以匹配一个可选的单词(除非这个单词只有一个字母)。下面我将看到,通常你可以使用一些高级技术绕开这个限制。以 '^' 开头的模式只匹配目标串的开始部分,相似的,以 '$' 结尾的模式只匹配目标串的结尾部分。这不仅可以用来限制你要查找的模式,还可以定位(anchor)模式。比如:if string.find(s, "^%d") then ...检查字符串s是否以数字开头,而if string.find(s, "^[+-]?%d+$") then ...检查字符串s是否是一个整数。'%b' 用来匹配对称的字符。常写为 '%bxy' ,x和y是任意两个不同的字符;x作为匹配的开始,y作为匹配的结束。比如,'%b()' 匹配以 '(' 开始,以 ')' 结束的字符串:print(string.gsub("a (enclosed (in) parentheses) line", "%b()", ""))--& a line常用的这种模式有:'%b()' ,'%b[]','%b%{%}' 和 '%b&&'。你也可以使用任何字符作为分隔符。
阅读(...) 评论()所属专题:
无忧版本(本频道)无忧工具软件(本频道)无忧外挂(本频道)无忧登陆器(本频道)无忧私服站点程序(本频道)游戏引擎辅助专区(本频道)心意传奇系列软件(本频道)乐都传奇工具专集(本频道)传奇脚本编辑工具(本频道)传奇实用工具合集(本频道)传奇DB工具合集(本频道)传奇辅助工具合集(本频道)网游端口工具合集(本频道)人物数据工具合集(本频道)传奇安全工具合集(本频道)
下载权限:
继承栏目权限(当所属栏目为认证栏目时,建议选择此项)
所有会员(当所属栏目为开放栏目,想单独对某些下载进行下载权限设置,可以选择此项)
指定会员组(当所属栏目为开放栏目,想单独对某些下载进行下载权限设置,可以选择此项)
未验证会员
待审批会员
下载下载点数:
&&&& 如果大于0,则会员下载此下载时将消耗相应点数(设为9999时除外),游客将无法下载此下载。
重复收费:
不重复收费
距离上次收费时间
小时后重新收费
会员重复下载此下载
次后重新收费
上述两者都满足时重新收费
上述两者任一个满足时就重新收费
每下载一次就重复收费一次(建议不要使用)
分成比例:
% &&如果比例大于0,则将按比例把向下载者收取的点数支付给录入者
菜鸟的福音,界面中文操作
推荐使用第三方专业下载工具下载本站软件,使用 WinRAR v3.10 以上版本解压本站软件。
如果这个软件总是不能下载的请点击报告错误,谢谢合作!!
下载本站资源,如果服务器暂不能下载请过一段时间重试!
如果遇到什么问题,请到本站论坛去咨寻,我们将在那里提供更多 、更好的资源!
本站提供的一些商业软件是供学习研究之用,如用于商业用途,请购买正版。
热门相关信息
推荐相关信息
最新相关信息温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(1164)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'Lua中的表达式包括数字常量、字符串常量、变量、一元和二元运算符、函数调用。还可以是非传统的函数定义和表构造。',
blogAbstract:'\r\n这一期,我们将要学习表达式以及控制结构。\r\n什么是表达式呢?\r\n『Lua中的表达式包括数字常量、字符串常量、变量、一元和二元运算符、函数调用。还可以是非传统的函数定义和表构造。 』\r\n简单地说,表达式就是可以通过计算来得到它的值的一个式子。你可以调用函数得到函数的返回值,或者是进行逻辑判断得到布尔值……表达式返回的值并不限于某种类型。举个例子吧:\r\n\"0\" == 0&&&&&& -- false\r\n2 & 15&&&&&&&& -- true\r\n\"1\"..\"2\"&&&&&& &-- 12',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:8,
publishTime:8,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}求变量字符加到全局变量并能读取的办法!!!急求!!【lua吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:7,040贴子:
求变量字符加到全局变量并能读取的办法!!!急求!!收藏
求变量字符加到全局变量并能读取的办法例 全局变量为x_bl[1] = {tx1= 3,tx2 = 4,tx3 = 5} 现在,我得到一个变量2,local bl2 = 2要取到常量中的 tx2的数量如pint(x_bl[1].tx..bl2)怎么样才能正确读取到tx2中的那个4??
猎聘网,专为经理人提供500强企业高薪职位,实时发布lua招聘信息.让经理人求职安全无忧,圆您高薪梦!
x_bl[1]["tx"..bl2]
研究了好久才解决,如果同样有这个问题的朋友参考下这里需要用到
_G //调用全局变量模块例bl2 = 222得到一个临时变量 为local lsbl = 2那么就可以pint(_G["bl"..lsbl]) ;这样就连接成功,得到全局变量里的bl2 ,显示
222数组里的东东不能直接这样连接所以只需要新建一个全局变量来加载他例数组:x_mnlb[1] = {tx1=2,tx2=3,tx3=4}全局1mnlb1, mnlb2, mnlb3, = 0,0,0在需要调用的地方加载一下mnlbif x_mnlb[1] .tx1 ~= 0 thenmnlb1 = x_mnlb[1] .tx1end2,3,...一样这样我们就把数组里的数值给予了一个新的全局变量这会如果得到临时变量就可以转了local lsbl= 2pint(_G["mnlb"..lsbl])这样就会显示出x_mnlb[1] tx2的内容
我想说不用setfenv这种函数最好
其实还有个简单方法:写个循环读出来。local
result for k,v in pairs(x_bl[1]) do
if k==&tx&..bl2 then
result = v
end end print (result )
这两天自己程序中碰到类似问题,直接用数组下标就读出来了。于是想到楼主这个帖子,翻出来重新回一下。二楼的方法是对的,没必要弄那么复杂。
我也觉得2楼是对的……
登录百度帐号推荐应用nginx 在nginx中集成lua脚本:添加自定义Http头,封IP等 - 为程序员服务
为程序员服务
在nginx中集成lua脚本:添加自定义Http头,封IP等
这几个月里,我们逐步把Lua集成到Mixlr的前端Nginx配置中。
Lua是一个可以嵌入到Nginx配置文件中的动态脚本语言,从而可以在Nginx请求处理的任何阶段执行各种Lua代码。刚开始我们只是用Lua 把请求路由到后端服务器,但是它对我们架构的作用超出了我们的预期。下面就讲讲我们所做的工作。
强制搜索引擎只索引
Google把子域名当作完全独立的网站,我们不希望爬虫抓取子域名的页面,降低我们的Page rank。
location / {
header_filter_by_lua '
if ngx.var.query_string and ngx.re.match( ngx.var.query_string, &^([0-9]{10})$& ) then
ngx.header[&Expires&] = ngx.http_time( ngx.time() +
ngx.header[&Cache-Control&] = &max-age=&;
如果对robots.txt的请求不是域名的话,则内部重写到robots_diallow.txt,虽然标准的重写指令也可以实现这个需求,但是 Lua的实现更容易理解和维护。
根据程序逻辑设置响应头
Lua提供了比Nginx默认配置规则更加灵活的设置方式。 在下面的例子中,我们要保证正确设置响应头,这样浏览器如果发送了指定请求头后,就可以 无限期缓存静态文件,是的用户只需下载一次即可。
这个重写规则使得任何静态文件,如果请求参数中包含时间戳值,那么就设置相应的Expires和Cache-Control响应头。
location / {
header_filter_by_lua '
if ngx.var.query_string and ngx.re.match( ngx.var.query_string, &^([0-9]{10})$& ) then
ngx.header[&Expires&] = ngx.http_time( ngx.time() +
ngx.header[&Cache-Control&] = &max-age=&;
try_files $uri @}
删除jQuery JSONP请求的时间戳参数
很多外部客户端请求JSONP接口时,都会包含一个时间戳类似的参数,从而导致Nginx proxy缓存无法命中(因为无法忽略指定的HTTP参数)。下面的 规则删除了时间戳参数,使得Nginx可以缓存upstream server的响应内容,减轻后端服务器的负载。
location / {
rewrite_by_lua '
if ngx.var.args ~= nil then
-- /some_request?_= becomes /some_request
local fixed_args, count = ngx.re.sub( ngx.var.args, &&?_=[0-9]+&, && );
if count & 0 then
return ngx.exec(ngx.var.uri, fixed_args);
把后端的慢请求日志记录到Nginx的错误日志
如果后端请求响应很慢,可以把它记录到Nginx的错误日志,以备后续追查。
location / {
log_by_lua '
if tonumber(ngx.var.upstream_response_time) &= 1 then
ngx.log(ngx.WARN, &[SLOW] Ngx upstream response time: & .. ngx.var.upstream_response_time .. &s from & .. ngx.var.upstream_addr);
基于Redis的实时IP封禁
某些情况下,需要阻止流氓爬虫的抓取,这可以通过专门的封禁设备去做,但是通过Lua,也可以实现简单版本的封禁。
lua_shared_dict banned_ips 1m;
location / {
access_by_lua '
local banned_ips = ngx.shared.banned_
local updated_at = banned_ips:get(&updated_at&);
-- only update banned_ips from Redis once every ten seconds:
if updated_at == nil or updated_at & ( ngx.now() - 10 ) then
local redis = require &resty.redis&;
local red = redis:new();
red:set_timeout(200);
local ok, err = red:connect(&your-redis-hostname&, 6379);
if not ok then
ngx.log(ngx.WARN, &Redis connection error retrieving banned_ips: & .. err);
local updated_banned_ips, err = red:smembers(&banned_ips&);
if err then
ngx.log(ngx.WARN, &Redis read error retrieving banned_ips: & .. err);
-- replace the locally stored banned_ips with the updated values:
banned_ips:flush_all();
for index, banned_ip in ipairs(updated_banned_ips) do
banned_ips:set(banned_ip, true);
banned_ips:set(&updated_at&, ngx.now());
if banned_ips:get(ngx.var.remote_addr) then
ngx.log(ngx.WARN, &Banned IP detected and refused access: & .. ngx.var.remote_addr);
return ngx.exit(ngx.HTTP_FORBIDDEN);
现在就可以阻止特定IP的访问:
ruby& $redis.sadd(&banned_ips&, &200.1.35.4&)
Nginx进程每隔10秒从Redis获取一次最新的禁止IP名单。需要注意的是,如果架构中使用了Haproxy这样类似的负载均衡服务器时, 需要把$remote_addr设置为正确的远端IP地址。
这个方法还可以用于HTTP User-Agent字段的检查,要求满足指定条件。
使用Nginx输出CSRF(form_authenticity_token)
Mixlr大量使用页面缓存,由此引入的一个问题是如何给每个页面输出会话级别的CSRF token。我们通过Nginx的子请求,从upstream web server 获取token,然后利用Nginx的SSI(server-side include)功能输出到页面中。这样既解决了CSRF攻击问题,也保证了cache能被正常利用。
location /csrf_token_endpoint {
include /opt/nginx/conf/proxy.
proxy_pass &http://upstream&;}
location @dynamic {
set $csrf_token '';
rewrite_by_lua '
-- Using a subrequest, we our upstream servers for the CSRF token for this session:
local csrf_capture = ngx.location.capture(&/csrf_token_endpoint&);
if csrf_capture.status == 200 then
ngx.var.csrf_token = csrf_capture.
-- if this is a new session, ensure it sticks by passing through the new session_id
-- to both the subsequent upstream request, and the response:
if not ngx.var.cookie_session then
local match = ngx.re.match(csrf_capture.header[&Set-Cookie&], &session=([a-zA-Z0-9_+=/+]+);&);
if match then
ngx.req.set_header(&Cookie&, &session=& .. match[1]);
ngx.header[&Set-Cookie&] = csrf_capture.header[&Set-Cookie&];
ngx.log(ngx.WARN, &No CSRF token returned from upstream, ignoring.&);
try_files /maintenance.html /rails_cache$uri @}
CSRF token生成 app/metal/csrf_token_endpoint.rb:
class CsrfTokenEndpoint
def self.call(env)
if env[&PATH_INFO&] =~ /^\/csrf_token_endpoint/
session = env[&rack.session&] || {}
token = session[:_csrf_token]
if token.nil?
token = SecureRandom.base64(32)
session[:_csrf_token] = token
[ 200, { &Content-Type& =& &text/plain& }, [ token ] ]
[404, {&Content-Type& =& &text/html&}, [&Not Found&]]
我们的模版文件示例:
&meta name=”csrf-param” value=”authenticity_token”/&
&meta name=”csrf-token” value=”&!–# echo var=”csrf_token” default=”” encoding=”none” –&”/&
Again you could make use of lua_shared_dict to store in memory the CSRF token for a particular session. This minimises the number of trips made to /csrf_token_endpoint.
原文链接://nginx-lua/
您可能的代码
相关聚客文章
荣誉:2088
相关专栏文章}

我要回帖

更多关于 lua 取字符串中间 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信