Skip to content

Commit

Permalink
渠道认证;mysql2redis;redis2nginx 完成
Browse files Browse the repository at this point in the history
  • Loading branch information
supermy committed Jun 8, 2015
1 parent 881e236 commit f553ea5
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 72 deletions.
2 changes: 1 addition & 1 deletion web+app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ nginx(tengine)+tomcat+mysql+memcached 集群
一键构造,一键启动,一键数据初始化。

> nginx 整合HttpRedis2Module/lua-resty-redis完成,http方式访问redis;
>
> mysql2redis.sh 将mysql 的数据同步到redis,通过linux 的crontab 进行配置;
>
> ## end
1 change: 1 addition & 0 deletions web+app/mynginx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ web(极限性能挖掘,可快速扩充)
nginx(tengine)+tomcat+mysql+memcached 集群
一键构造,一键启动,一键数据初始化。

> 渠道认证完成,部署的时候需要手动更改redis 的IP 地址。todo
> 升级lua由5.1.5 到5.3.0,支持goto ;相关插件升级到最新版本
> 语法校验 http://www.lua.org/demo.html
>
Expand Down
1 change: 1 addition & 0 deletions web+app/mynginx/nginx.d/lua-mysql.conf
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@ location /lua-mysql-test {
-- end
';


default_type 'text/plain';
}
2 changes: 2 additions & 0 deletions web+app/mynginx/nginx.d/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ http {

#access_by_lua_file '/usr/local/nginx/conf/nginx.d/token.lua';
access_by_lua_file '/usr/local/nginx/conf/nginx.d/redisip.lua';
#access_by_lua_file '/usr/local/nginx/conf/nginx.d/timer.lua';


#慢速响应记录日志
#log_by_lua '
Expand Down
189 changes: 120 additions & 69 deletions web+app/mynginx/nginx.d/redisip.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
local function isempty(s)
return s == nil or s == ''
return s == nil or s == '' or s == ngx.null
end

--支撑head或者cookie 获取参数
--支撑head或者cookie 获取参数;
--java 对渠道参数配置进行管理,并且将数据同步到redis

--环境初始化
--默认全局封禁时间,每秒访问次数,统计时间段;从redis 取渠道设置的阀值
Expand All @@ -22,7 +23,7 @@ cache:set_timeout(60000) --1分钟
if not ok then
ngx.log(ngx.ERR,">>>redis链接失败")

goto done
goto authdone

end

Expand All @@ -41,14 +42,67 @@ if isempty(myIp) then
ngx.say("没有获取到ip 地址");
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);

goto done
goto authdone
--ngx.exit(403)
end

--:::::::::::::::::::::
--所有的操作都进行并发控制;
--查询ip是否在封禁段内,若在则返回403错误代码
--因封禁时间会大于ip记录时间,故此处不对ip时间key和计数key做处理
is_bind , err = cache:get("bind_"..ngx.var.remote_addr)

ngx.log(ngx.ERR,is_bind == '1')

if is_bind == '1' then
ngx.log(ngx.ERR,">>>redis封禁......")

ngx.say("ip 地址已经被封禁");
--ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
ngx.exit(403)

goto authdone

end

start_time , err = cache:get("time_"..ngx.var.remote_addr)
ip_count , err = cache:get("count_"..ngx.var.remote_addr)

--如果ip记录时间大于指定时间间隔或者记录时间或者不存在ip时间key则重置时间key和计数key
--如果ip时间key小于时间间隔,则ip计数+1,且如果ip计数大于ip频率计数,则设置ip的封禁key为1
--同时设置封禁key的过期时间为封禁ip的时间

if start_time == ngx.null or os.time() - start_time > ip_time_out then

ngx.log(ngx.ERR,">>>设置初始值" .. ngx.var.remote_addr)

res , err = cache:set("time_"..ngx.var.remote_addr , os.time())
res , err = cache:set("count_"..ngx.var.remote_addr , 1)
else


ip_count = ip_count + 1

ngx.log(ngx.ERR,">>>计数" .. ip_count)

res , err = cache:incr("count_"..ngx.var.remote_addr)
if ip_count >= connect_count then

ngx.log(ngx.ERR,">>>设置为封禁" .. ngx.var.remote_addr)

res , err = cache:set("bind_"..ngx.var.remote_addr,1)
--设置生存时间 300 秒
res , err = cache:expire("bind_"..ngx.var.remote_addr,ip_bind_time)
end
end




--设置ctoken 数据
--telnet 192.168.59.103 6379/monitor/keys */set aa6f21ec0fcf008aa5250904985a817b 192.168.59.3/get aa6f21ec0fcf008aa5250904985a817b
--curl -v -b "ctoken=aa6f21ec0fcf008aa5250904985a817b" http://192.168.59.103/hello
--ab -n 5000 -c 200 -C ctoken=aa6f21ec0fcf008aa5250904985a817b http://192.168.59.103/hello
--如果已经动态分配ctoken,token 与IP 地址绑定;验证token 的有效性;则不进行认证,直接进行能力管控
ctoken = ngx.req.get_headers()["ctoken"]
if isempty(ctoken) then
Expand Down Expand Up @@ -77,24 +131,24 @@ end

--进行认证

--获取从head 或者cookie 中渠道编码code/渠道秘钥-动态生成
--curl -v -b "channelCode=1234;ChannelSecretkey=aa6f21ec0fcf008aa5250904985a817b" http://192.168.59.103/hello1
--获取从head 或者cookie 中渠道编码code/渠道秘钥-动态生成 ab -C 会更改cookie 的名称
--curl -v -b "ChannelCode=test;ChannelSecretkey=37966a74c488ce7b74db90d065aa7cc3" http://192.168.59.103/hello
--mysql2redis.sh 同步数据
--ab -n 5000 -c 200 -H "Cookie:ChannelCode=1234;ChannelSecretkey=37966a74c488ce7b74db90d065aa7cc3" http://192.168.59.103/hello
channel_code = ngx.req.get_headers()["ChannelCode"]
channel_secretkey = ngx.req.get_headers()["ChannelSecretkey"]

if isempty(channel_code) then
channel_code = ngx.var.cookie_ChannelCode
ngx.log(ngx.DEBUG,">>>channel_code:" .. channel_code)

end

if isempty(channel_secretkey) then
channel_secretkey = ngx.var.cookie_ChannelSecretkey
ngx.log(ngx.DEBUG,">>>channel_secretkey:" .. channel_secretkey)
end

if isempty(channel_code) or isempty(channel_secretkey) then

ngx.log(ngx.WARN,"传递的参数不全,或者名称不对")
ngx.log(ngx.ERR,"传递的参数不全,或者名称不对")

--ngx.header.content_type = "application/json; charset=UTF-8";

Expand All @@ -103,53 +157,79 @@ if isempty(channel_code) or isempty(channel_secretkey) then

--ngx.exit(403)

goto done
goto authdone
end


---telnet 192.168.59.103 6379/monitor/keys */set 1234ip_bind_time 300/set 1234ip_time_out 60 /set 1234connect_count 100
---set 1234pwd 111111/set 1234iplist 192.168.59.3/set 1234token_expire 1/
--设置渠道的封禁时间,访问频率和统计时间段
--注意数字和字符串类型
if not isempty(channel_code) then
--渠道带宽控制
ip_bind_time , err = cache:get(channel_code.."ip_bind_time")
ip_time_out , err = cache:get(channel_code.."ip_time_out")
connect_count ,err = cache:get(channel_code.."connect_count")

--[[
local channel_ip_bind_time , err = cache:get(channel_code.."ip_bind_time")
local channel_ip_time_out , err = cache:get(channel_code.."ip_time_out")
local channel_connect_count ,err = cache:get(channel_code.."connect_count")
local channel_pwd ,err = cache:get(channel_code.."pwd") --秘钥盐渍
local channel_iplist ,err = cache:get(channel_code.."iplist") --渠道ip 地址
local channel_token ,err = cache:get(channel_code.."token") --渠道令牌
local channel_token_expire ,err = cache:get(channel_code.."token_expire") --渠道有效期
--]]

local channel_ip_bind_time , err = cache:hget("hash_"..channel_code,"ip_bind_time")
local channel_ip_time_out , err = cache:hget("hash_"..channel_code,"ip_time_out")
local channel_connect_count ,err = cache:hget("hash_"..channel_code,"connect_count")

if not ip_bind_time or not ip_time_out or not connect_count
or not channel_pwd or not channel_iplist or not channel_token or not channel_token_expire then
local channel_pwd ,err = cache:hget("hash_"..channel_code,"pwd") --秘钥盐渍
local channel_iplist ,err = cache:hget("hash_"..channel_code,"iplist") --渠道ip 地址
local channel_token ,err = cache:hget("hash_"..channel_code,"token") --渠道令牌
local channel_token_expire ,err = cache:hget("hash_"..channel_code,"token_expire") --渠道有效期

ngx.log(ngx.ERR,"渠道号没有是生效")

--ngx.log(ngx.ERR,channel_connect_count)
ngx.log(ngx.ERR,channel_connect_count == ngx.null)

if isempty(channel_ip_bind_time) or isempty(channel_ip_time_out) or isempty(channel_connect_count)
or isempty(channel_pwd) or isempty(channel_iplist) or isempty(channel_token) or isempty(channel_token_expire) then

ngx.log(ngx.ERR,"渠道号没有生效")
ngx.say("渠道号没有生效");
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);

else
ip_bind_time=channel_ip_bind_time
ip_time_out=channel_ip_time_out
connect_count=channel_connect_count

end

_ , q = string.find(channel_iplist , myIp )
if q <= 0 then
ngx.log(ngx.ERR,"实际ip 地址与渠道设置的ip 地址不匹配")
if isempty(q) then

ngx.log(ngx.ERR,"实际ip 地址与渠道设置的ip 地址不匹配")

ngx.say("实际ip 地址与渠道设置的ip 地址不匹配");
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
--ngx.exit(403)
goto done
goto authdone
end

--验证秘钥 是否有效
local server_secretkey = ngx.md5( channel_code .. myIp .. channel_pwd)
ngx.log(ngx.ERR,"server秘钥"..server_secretkey)

if channel_secretkey ~= server_secretkey then

ngx.log(ngx.WARN,"秘钥不匹配")
ngx.log(ngx.ERR,"秘钥不匹配")

ngx.say("秘钥不匹配");
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);

--ngx.exit(403)
goto done
goto authdone
end

--给渠道返回一个token,有效期
Expand All @@ -158,62 +238,33 @@ if not isempty(channel_code) then
--设置生存时间 天数转换为秒
res , err = cache:expire(channel_code .. ctoken,channel_token_expire*60*60*60)

ngx.say("新的令牌,有效期:" .. channel_token_expire*60*60*60);
ngx.exit(ngx.HTTP_OK);
ngx.log(ngx.ERR,"新的令牌"..ctoken..",有效期:" .. channel_token_expire*60*60*60)

goto done
tokenvalue = "{status:200,message:ok,ctoken:"..ctoken..",expire:" .. channel_token_expire*60*60*60 .. "}"

end
ngx.say(tokenvalue);

--认证完成,下面是进行并发控制
::authdone::
--[[#local cjson = require "cjson"
#local data = {}
# data.message= "ok";
# data.status=200;
# data.ctoken=ctoken;
# data.token_expire=channel_token_expire*60*60*60;
# data.attachment={}
--查询ip是否在封禁段内,若在则返回403错误代码
--因封禁时间会大于ip记录时间,故此处不对ip时间key和计数key做处理
is_bind , err = cache:get("bind_"..ngx.var.remote_addr)
ngx.log(ngx.ERR,is_bind == '1')
#local jsonvalue=cjson.encode(data);
if is_bind == '1' then
ngx.log(ngx.INFO,">>>redis封禁......")
#ngx.say(jsonvalue);
--]]

ngx.say("ip 地址已经被封禁");
--ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
ngx.exit(403)
ngx.exit(ngx.HTTP_OK);

goto done
goto authdone

end

start_time , err = cache:get("time_"..ngx.var.remote_addr)
ip_count , err = cache:get("count_"..ngx.var.remote_addr)

--如果ip记录时间大于指定时间间隔或者记录时间或者不存在ip时间key则重置时间key和计数key
--如果ip时间key小于时间间隔,则ip计数+1,且如果ip计数大于ip频率计数,则设置ip的封禁key为1
--同时设置封禁key的过期时间为封禁ip的时间

if start_time == ngx.null or os.time() - start_time > ip_time_out then

ngx.log(ngx.WARN,">>>设置初始值" .. ngx.var.remote_addr)

res , err = cache:set("time_"..ngx.var.remote_addr , os.time())
res , err = cache:set("count_"..ngx.var.remote_addr , 1)
else


ip_count = ip_count + 1

ngx.log(ngx.ERR,">>>计数" .. ip_count)

res , err = cache:incr("count_"..ngx.var.remote_addr)
if ip_count >= connect_count then

ngx.log(ngx.ERR,">>>设置为封禁" .. ngx.var.remote_addr)

res , err = cache:set("bind_"..ngx.var.remote_addr,1)
--设置生存时间 300 秒
res , err = cache:expire("bind_"..ngx.var.remote_addr,ip_bind_time)
end
end

::done::
--认证完成,下面是进行并发控制
::authdone::
local ok,err = cache:close()

Loading

0 comments on commit f553ea5

Please sign in to comment.