nginx-lua实现简单权限控制
1,依赖软件:nginx(openresty) mysql(存储用户表)redis(存储用户登录token,有效期1周)
create table account(
uid integer not null auto_increment,
username varchar(64),
password varchar(64),
email varchar(256),
primary key(uid),
unique key email(email)
);
nginx配置文件如下:
location = /account {
lua_need_request_body on;
content_by_lua_file /usr/local/FRIENDS/code_lua/account.lua;
}
location = /api {
access_by_lua '
local tokentool = require "tokentool"
local args = ngx.req.get_uri_args(10)
if args.token == nil then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local ret = tokentool.has_token(args.token)
if ret == ngx.null then
ngx.exit(ngx.HTTP_FORBIDDEN)
elseif ret == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
';
content_by_lua '
ngx.say("token ok")
';
}
2,依赖库:nginx-lua , lua-redis(读取redis), lua-mysql(读取mysql), lua-string(加解密)
3,代码如下:
account.lua(入口)
local mysql = require "resty.mysql"
local tokentool = require "tokentool" -- post only
local method = ngx.req.get_method()
if method ~= "POST" then
ngx.exit(ngx.HTTP_FORBIDDEN)
return
end -- get args
local args = ngx.req.get_uri_args()
if args.act ~= "register" and args.act ~= "login" and args.act ~= "logout" and args.act ~= "updatepwd" then
ngx.exit(ngx.HTTP_BAD_REQUEST)
return
end local postargs = ngx.req.get_post_args() -- connect to mysql;
local function connect()
local db, err = mysql:new()
if not db then
return false
end
db:set_timeout() local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = ,
database = "friends",
user = "root",
password = "",
max_packet_size = * } if not ok then
return false
end
return db
end function register(pargs)
if pargs.username == nil then
pargs.username = ""
end
if pargs.email == nil or pargs.password == nil then
ngx.exit(ngx.HTTP_BAD_REQUEST)
return
end local db = connect()
if db == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end local res, err, errno, sqlstate = db:query("insert into account(username, password, email) "
.. "values (\'".. pargs.username .."\',\'".. pargs.password .."\',\'".. pargs.email .."\')")
if not res then
ngx.exit(ngx.HTTP_NOT_ALLOWED)
return
end local uid = res.insert_id
local token, rawtoken = tokentool.gen_token(uid) local ret = tokentool.add_token(token, rawtoken)
if ret == true then
ngx.say(token)
else
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end function login(pargs)
if pargs.email == nil or pargs.password == nil then
ngx.exit(ngx.HTTP_BAD_REQUEST)
return
end local db = connect()
if db == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end local res, err, errno, sqlstate = db:query("select uid from account where email=\'".. pargs.email .."\' and password=\'".. pargs.password .."\' limit 1", )
if not res then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end
--local cjson = require "cjson"
--ngx.say(cjson.encode(res))
if res[] == nil then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local uid = res[].uid
local token, rawtoken = tokentool.gen_token(uid) local ret = tokentool.add_token(token, rawtoken)
if ret == true then
ngx.say(token)
else
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end function logout(pargs)
if pargs.token == nil then
ngx.exit(ngx.HTTP_BAD_REQUEST)
return
end tokentool.del_token(pargs.token)
ngx.say("ok")
end -- to be done
function updatepwd(pargs)
local db = connect()
if db == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end
ngx.say(pargs.username .. pargs.newpassword)
end if args.act == "register" then
register(postargs)
elseif args.act == "login" then
login(postargs)
elseif args.act == "updatepwd" then
updatepwd(postargs)
elseif args.act == "logout" then
logout(postargs)
end
tokentool.lua(用redis存取token,放到序号为1的redis库中)
module("tokentool", package.seeall)
local redis = require "resty.redis"
local aes = require "resty.aes"
local str = require "resty.string"
local alive_time = * *
local redis_host = "127.0.0.1"
local redis_port =
local function connect()
local red = redis:new()
red:set_timeout()
local ok, err = red:connect(redis_host, redis_port)
if not ok then
return false
end
ok, err = red:select()
if not ok then
return false
end
return red
end
function add_token(token, raw_token)
local red = connect()
if red == false then
return false
end
local ok, err = red:setex(token, alive_time, raw_token)
if not ok then
return false
end
return true
end
function del_token(token)
local red = connect()
if red == false then
return
end
red:del(token)
end
function has_token(token)
local red = connect()
if red == false then
return false
end
local res, err = red:get(token)
if not res then
return false
end
return res
end
-- generate token
function gen_token(uid)
local rawtoken = uid .. " " .. ngx.now()
local aes_128_cbc_md5 = aes:new("friends_secret_key")
local encrypted = aes_128_cbc_md5:encrypt(rawtoken)
local token = str.to_hex(encrypted)
return token, rawtoken
end
使用方法:
1,注册用户,返回token
curl -d "username=ciaos&email=aaa@126.com&password=12345" http://localhost/account?act=register
2,登录,返回token
curl -d "email=aaa@126.com&password=12345" http://localhost/account?act=login
3,注销,删除token,返回ok
curl -d "token=0bab442cd24cd055b58665d4156939655d72a7c282c916778ef2c63be9971085" http://localhost/account?act=logout
结合codeigniter还需做如下配置
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 last;
break;
}
location ~ \.php($|/) {
access_by_lua '
local tokentool = require "tokentool"
local args = ngx.req.get_uri_args(10)
if args.token == nil then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local ret = tokentool.has_token(args.token)
if ret == ngx.null then
ngx.exit(ngx.HTTP_FORBIDDEN)
elseif ret == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.req.set_uri_args({token=ret})
';
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
需要在网站根目录放置空文件account,不然nginx处理/account时会走到找不到request_filename的这个location里面。
附(ngx-lua的long-polling实现):
--[[ nginx.conf
location /message {
default_type text/plain;
access_by_lua '
local tokentool = require "tokentool"
local args = ngx.req.get_uri_args(10)
if args.token == nil then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local ret = tokentool.has_token(args.token)
if ret == ngx.null then
ngx.exit(ngx.HTTP_FORBIDDEN)
elseif ret == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.req.set_uri_args({token=ret})
'; content_by_lua_file /usr/local/FRIENDS/code_lua/message.lua;
}
--]] -- message.lua local redis = require "resty.redis" local redis_host = "127.0.0.1"
local redis_port = local function connect()
local red = redis:new()
red:set_timeout( * )
local ok, err = red:connect(redis_host, redis_port)
if not ok then
return false
end return red
end local function string_split (string, split)
local list = {}
local pos =
if string.find("", split, ) then -- this would result in endless loops
end
while do
local first, last = string.find(string, split, pos)
if first then -- found
table.insert(list, string.sub(string, pos, first-))
pos = last+
else
table.insert(list, string.sub(string, pos))
break
end
end return list
end local args = ngx.req.get_uri_args()
local params = string_split(args.token, ' ')
local mymailbox = params[] .. "_mailbox" local red = connect()
if red == false then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end local res, err = red:llen(mymailbox)
if err ~= nil then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end if res == then
res, err = red:brpop(mymailbox, )
ngx.print('[')
for k, v in ipairs(res) do
if k == then
ngx.print(v)
end
end
ngx.print(']')
else
if res > then
res =
end
local i =
ngx.print('[')
for i=, res - , do
local msg, _ = red:rpop(mymailbox)
ngx.print(msg)
if i ~= res - then
ngx.print(',')
end
end
ngx.print(']')
end
ngx.exit(ngx.HTTP_OK)
nginx-lua实现简单权限控制的更多相关文章
- NGINX + LUA实现复杂的控制
安装lua_nginx_module 模块 lua_nginx_module 可以一步步的安装,也可以直接用淘宝的OpenResty Centos和debian的安装就简单了.. 这里说下freebs ...
- nginx+lua实现简单的waf网页防火墙功能
原文:http://www.2cto.com/net/201608/534272.html 安装LuaJIT http://luajit.org/download/LuaJIT-2.0.4.tar.g ...
- NGINX + LUA实现复杂的控制 --源自http://outofmemory.cn/code-snippet/14396/nginx-and-lua
安装lua_nginx_module 模块 lua_nginx_module 可以一步步的安装,也可以直接用淘宝的OpenResty Centos和debian的安装就简单了.. 这里说下freebs ...
- nginx+lua构建简单waf网页防火墙
需求背景 类似于论坛型的网站经常会被黑掉,除了增加硬件防护感觉效果还是不太好,还会偶尔被黑,waf的功能正好实现了这个需求. waf的作用: 防止sql注入,本地包含,部分溢出,fuzzing测试,x ...
- 通过lua进行nginx的权限控制
nginx_lua的安装 nginx使用luajit进行编译安装 使用openresty进行yum安装 openresty中将lua和nginx进行封装,详情可查看openresty官网 openre ...
- 使用nginx和iptables做访问权限控制(IP和MAC)
之前配置的服务器,相当于对整个内网都是公开的 而且,除了可以通过80端口的nginx来间接访问各项服务,也可以绕过nginx,直接ip地址加端口访问对应服务 这是不对的啊,所以我们要做一些限制 因为只 ...
- shiro权限控制的简单实现
权限控制常用的有shiro.spring security,两者相比较,各有优缺点,此篇文章以shiro为例,实现系统的权限控制. 一.数据库的设计 简单的五张表,用户.角色.权限及关联表: CREA ...
- webapi框架搭建-安全机制(三)-简单的基于角色的权限控制
webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...
- 简单的RBAC用户角色权限控制
Java web项目中,无论项目是大是小,或多或少都会涉及到用户访问权限的控制,权限管理总体的设计思路就是,不该看的不看,不该做的不做!据我目前的了解,我所知道的几种实现访问权限控制的方式有: JQu ...
随机推荐
- hdu3507
题意: 给n(n<=10^6)个非负数字,放在一个数组num中,再给一个特殊值m.求将这个数组分成任意多个区间,每个区间[a,b]的值定义为( sigma(num[i] | (a<=i&l ...
- CSS截取字符串
/*溢出的字...处理*/ .updatecsssubstring { text-overflow: ellipsis; -o-text-overflow: ellipsis; white-space ...
- IE8,9下的ajax缓存问题
最近在做一个网站的登录注册框,前端使用了jquery.由于sign和login不是在单独的页面上,而是以一个弹出框出现.所以决定使用ajax来实现注册和登录功能.本以为可以一帆风顺,结果在测试的时候发 ...
- linux杂记(?)命令别名——alias
linux中的命令别名--alias linux中的命令别名--alias 1. 用命令alias可以查询系统中有哪些可用的命令别名 2.添加命令别名 回车查看, 别名建立成功 3.查询命令的地址ty ...
- css3图片3D翻转效果
点击图片看翻转效果 html结构 <div class="flip"> <div class="front"> <img src= ...
- [暂停一天]从零开始PHP学习 - 第六天
今天这个系列没有时间去写了 在公司完善一个项目 已经备好6瓶咖啡 两天 + 一夜 完成这个项目 真是苦逼 诶 反正这几天 明白一个道理:别以为你多牛B 你不会的东西多了! 比你牛B的人也多 ...
- [Java]利用栈判断括号是否完整配对
利用栈实现判断字符串中的括号是否都是配对的. 主要算法是依次读取字符串中的每一个字符,如果是左括号则将左括号压入栈中,如果是右括号则从栈中弹出最上面的字符,若两者不是同种括号或栈内已经没有字符就返回f ...
- 射频识别技术漫谈(28)——基于MF1射频卡的酒店门锁设计
电子门锁是现代星级酒店管理电子化.智能化的重要电子设备.相较于传统的机械锁,基于RFID技术的电子门锁使用方便,易于管理,安全性高,可实现对开锁用户的分优先级自动管理,对房间入住信息实现自动统计与报表 ...
- 脑波设备mindwaveTGC接口示例
TGC是一个后台应用程序,它负责和脑波设备建立连接,并获取数据,另一方面,它打开了一个端口在监听,让二次开发的应用程序,可以通过socket连接到这个TGC后台程序,获取脑波数据并展示,这种接口适合非 ...
- HDU 3362 Fix
题目大意:题目给出n(n <= 18)个点的二维坐标,并说明某些点是被固定了的,其余则没固定,要求添加一些边,使得还没被固定的点变成固定的,当一个没固定的点和两个固定了的点连接后,该点就被间接固 ...