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 ...
随机推荐
- IO库 8.5
题目:重写8.4中的函数,将每一个单词作为一个独立的元素进行存储. #include <iostream> #include <fstream> #include <st ...
- php ZIP压缩类实例分享
php ZIP压缩类实例分享 <?php $zipfiles =array("/root/pooy/test1.txt","/root/pooy/test2.txt ...
- 这两天写的mybatis配置文件,主要是有输出和输入的存储过程
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...
- Yii2.0中文开发向导——自定义日志文件写日志
头部引入log类use yii\log\FileTarget; $time = microtime(true);$log = new FileTarget();$log->logFile = Y ...
- Fedora 19下Guacamole的安装使用
由于我要使用RDP实现web远程桌面,因此需要用到了Guacamole这个开源的软件.之前用Ubuntu12.04折腾了一晚上,也没有找到依赖库文件,而Guacamole的官方安装说明却没有介绍这个依 ...
- 转:CI伪静态化
去掉php框架CI默认url中的index.php 2010-03-17 17:33:07| 分类: php框架ci |字号 订阅 CI默认的rewrite url中是类似这样的,例如你的CI根 ...
- HDU 5730 Shell Necklace(CDQ分治+FFT)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...
- MySQL性能调优的方法
第一种方法 1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的 性能,我们可以将表中字 ...
- String、StringBuffer和StringBuild的区别
public class Test1 { public static void stringReplace (String text) { text = text.replace('j','i') ; ...
- linux 使用ssh到远端并且使用while的坑
如果要使用ssh批量登录到其它系统上操作时,我们会采用循环的方式去处理,那么这里存在一个巨大坑,你必须要小心了. 现在是想用一个脚本获取远程服务器端/root下面的文件: #!/bin/bash ca ...