1,依赖软件:nginx(openresty) mysql(存储用户表)redis(存储用户登录token,有效期1周)

  1. create table account(
  2. uid integer not null auto_increment,
  3. username varchar(64),
  4. password varchar(64),
  5. email varchar(256),
  6. primary key(uid),
  7. unique key email(email)
  8. );

nginx配置文件如下:

  1. location = /account {
  2. lua_need_request_body on;
  3. content_by_lua_file /usr/local/FRIENDS/code_lua/account.lua;
  4. }
  5.  
  6. location = /api {
  7. access_by_lua '
  8. local tokentool = require "tokentool"
  9. local args = ngx.req.get_uri_args(10)
  10. if args.token == nil then
  11. ngx.exit(ngx.HTTP_FORBIDDEN)
  12. end
  13. local ret = tokentool.has_token(args.token)
  14. if ret == ngx.null then
  15. ngx.exit(ngx.HTTP_FORBIDDEN)
  16. elseif ret == false then
  17. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  18. end
  19. ';
  20.  
  21. content_by_lua '
  22. ngx.say("token ok")
  23. ';
  24. }

2,依赖库:nginx-lua , lua-redis(读取redis), lua-mysql(读取mysql), lua-string(加解密)

3,代码如下:

account.lua(入口)

  1. local mysql = require "resty.mysql"
  2. local tokentool = require "tokentool"
  3.  
  4. -- post only
  5. local method = ngx.req.get_method()
  6. if method ~= "POST" then
  7. ngx.exit(ngx.HTTP_FORBIDDEN)
  8. return
  9. end
  10.  
  11. -- get args
  12. local args = ngx.req.get_uri_args()
  13. if args.act ~= "register" and args.act ~= "login" and args.act ~= "logout" and args.act ~= "updatepwd" then
  14. ngx.exit(ngx.HTTP_BAD_REQUEST)
  15. return
  16. end
  17.  
  18. local postargs = ngx.req.get_post_args()
  19.  
  20. -- connect to mysql;
  21. local function connect()
  22. local db, err = mysql:new()
  23. if not db then
  24. return false
  25. end
  26. db:set_timeout()
  27.  
  28. local ok, err, errno, sqlstate = db:connect{
  29. host = "127.0.0.1",
  30. port = ,
  31. database = "friends",
  32. user = "root",
  33. password = "",
  34. max_packet_size = * }
  35.  
  36. if not ok then
  37. return false
  38. end
  39. return db
  40. end
  41.  
  42. function register(pargs)
  43. if pargs.username == nil then
  44. pargs.username = ""
  45. end
  46. if pargs.email == nil or pargs.password == nil then
  47. ngx.exit(ngx.HTTP_BAD_REQUEST)
  48. return
  49. end
  50.  
  51. local db = connect()
  52. if db == false then
  53. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  54. return
  55. end
  56.  
  57. local res, err, errno, sqlstate = db:query("insert into account(username, password, email) "
  58. .. "values (\'".. pargs.username .."\',\'".. pargs.password .."\',\'".. pargs.email .."\')")
  59. if not res then
  60. ngx.exit(ngx.HTTP_NOT_ALLOWED)
  61. return
  62. end
  63.  
  64. local uid = res.insert_id
  65. local token, rawtoken = tokentool.gen_token(uid)
  66.  
  67. local ret = tokentool.add_token(token, rawtoken)
  68. if ret == true then
  69. ngx.say(token)
  70. else
  71. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  72. end
  73. end
  74.  
  75. function login(pargs)
  76. if pargs.email == nil or pargs.password == nil then
  77. ngx.exit(ngx.HTTP_BAD_REQUEST)
  78. return
  79. end
  80.  
  81. local db = connect()
  82. if db == false then
  83. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  84. return
  85. end
  86.  
  87. local res, err, errno, sqlstate = db:query("select uid from account where email=\'".. pargs.email .."\' and password=\'".. pargs.password .."\' limit 1", )
  88. if not res then
  89. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  90. return
  91. end
  92. --local cjson = require "cjson"
  93. --ngx.say(cjson.encode(res))
  94. if res[] == nil then
  95. ngx.exit(ngx.HTTP_FORBIDDEN)
  96. end
  97. local uid = res[].uid
  98. local token, rawtoken = tokentool.gen_token(uid)
  99.  
  100. local ret = tokentool.add_token(token, rawtoken)
  101. if ret == true then
  102. ngx.say(token)
  103. else
  104. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  105. end
  106. end
  107.  
  108. function logout(pargs)
  109. if pargs.token == nil then
  110. ngx.exit(ngx.HTTP_BAD_REQUEST)
  111. return
  112. end
  113.  
  114. tokentool.del_token(pargs.token)
  115. ngx.say("ok")
  116. end
  117.  
  118. -- to be done
  119. function updatepwd(pargs)
  120. local db = connect()
  121. if db == false then
  122. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  123. return
  124. end
  125. ngx.say(pargs.username .. pargs.newpassword)
  126. end
  127.  
  128. if args.act == "register" then
  129. register(postargs)
  130. elseif args.act == "login" then
  131. login(postargs)
  132. elseif args.act == "updatepwd" then
  133. updatepwd(postargs)
  134. elseif args.act == "logout" then
  135. logout(postargs)
  136. end

tokentool.lua(用redis存取token,放到序号为1的redis库中)

  1. module("tokentool", package.seeall)
  2. local redis = require "resty.redis"
  3. local aes = require "resty.aes"
  4. local str = require "resty.string"
  5.  
  6. local alive_time = * *
  7. local redis_host = "127.0.0.1"
  8. local redis_port =
  9.  
  10. local function connect()
  11. local red = redis:new()
  12. red:set_timeout()
  13. local ok, err = red:connect(redis_host, redis_port)
  14. if not ok then
  15. return false
  16. end
  17. ok, err = red:select()
  18. if not ok then
  19. return false
  20. end
  21. return red
  22. end
  23.  
  24. function add_token(token, raw_token)
  25. local red = connect()
  26. if red == false then
  27. return false
  28. end
  29.  
  30. local ok, err = red:setex(token, alive_time, raw_token)
  31. if not ok then
  32. return false
  33. end
  34. return true
  35. end
  36.  
  37. function del_token(token)
  38. local red = connect()
  39. if red == false then
  40. return
  41. end
  42. red:del(token)
  43. end
  44.  
  45. function has_token(token)
  46. local red = connect()
  47. if red == false then
  48. return false
  49. end
  50.  
  51. local res, err = red:get(token)
  52. if not res then
  53. return false
  54. end
  55. return res
  56. end
  57.  
  58. -- generate token
  59. function gen_token(uid)
  60. local rawtoken = uid .. " " .. ngx.now()
  61. local aes_128_cbc_md5 = aes:new("friends_secret_key")
  62. local encrypted = aes_128_cbc_md5:encrypt(rawtoken)
  63. local token = str.to_hex(encrypted)
  64. return token, rawtoken
  65. end

使用方法:

  1. 1,注册用户,返回token
  2. curl -d "username=ciaos&email=aaa@126.com&password=12345" http://localhost/account?act=register
  3. 2,登录,返回token
  4. curl -d "email=aaa@126.com&password=12345" http://localhost/account?act=login
  5. 3,注销,删除token,返回ok
  6. curl -d "token=0bab442cd24cd055b58665d4156939655d72a7c282c916778ef2c63be9971085" http://localhost/account?act=logout

结合codeigniter还需做如下配置

  1. if (!-e $request_filename) {
  2. rewrite ^/(.*)$ /index.php/$1 last;
  3. break;
  4. }
  5.  
  6. location ~ \.php($|/) {
  7. access_by_lua '
  8. local tokentool = require "tokentool"
  9. local args = ngx.req.get_uri_args(10)
  10. if args.token == nil then
  11. ngx.exit(ngx.HTTP_FORBIDDEN)
  12. end
  13. local ret = tokentool.has_token(args.token)
  14. if ret == ngx.null then
  15. ngx.exit(ngx.HTTP_FORBIDDEN)
  16. elseif ret == false then
  17. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  18. end
  19. ngx.req.set_uri_args({token=ret})
  20. ';
  21. fastcgi_pass 127.0.0.1:9000;
  22. fastcgi_index index.php;
  23. fastcgi_split_path_info ^(.+\.php)(.*)$;
  24. fastcgi_param PATH_INFO $fastcgi_path_info;
  25. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  26. include fastcgi_params;
  27. }

需要在网站根目录放置空文件account,不然nginx处理/account时会走到找不到request_filename的这个location里面。

附(ngx-lua的long-polling实现):

  1. --[[ nginx.conf
  2. location /message {
  3. default_type text/plain;
  4. access_by_lua '
  5. local tokentool = require "tokentool"
  6. local args = ngx.req.get_uri_args(10)
  7. if args.token == nil then
  8. ngx.exit(ngx.HTTP_FORBIDDEN)
  9. end
  10. local ret = tokentool.has_token(args.token)
  11. if ret == ngx.null then
  12. ngx.exit(ngx.HTTP_FORBIDDEN)
  13. elseif ret == false then
  14. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  15. end
  16. ngx.req.set_uri_args({token=ret})
  17. ';
  18.  
  19. content_by_lua_file /usr/local/FRIENDS/code_lua/message.lua;
  20. }
  21. --]]
  22.  
  23. -- message.lua
  24.  
  25. local redis = require "resty.redis"
  26.  
  27. local redis_host = "127.0.0.1"
  28. local redis_port =
  29.  
  30. local function connect()
  31. local red = redis:new()
  32. red:set_timeout( * )
  33. local ok, err = red:connect(redis_host, redis_port)
  34. if not ok then
  35. return false
  36. end
  37.  
  38. return red
  39. end
  40.  
  41. local function string_split (string, split)
  42. local list = {}
  43. local pos =
  44. if string.find("", split, ) then -- this would result in endless loops
  45. end
  46. while do
  47. local first, last = string.find(string, split, pos)
  48. if first then -- found
  49. table.insert(list, string.sub(string, pos, first-))
  50. pos = last+
  51. else
  52. table.insert(list, string.sub(string, pos))
  53. break
  54. end
  55. end
  56.  
  57. return list
  58. end
  59.  
  60. local args = ngx.req.get_uri_args()
  61. local params = string_split(args.token, ' ')
  62. local mymailbox = params[] .. "_mailbox"
  63.  
  64. local red = connect()
  65. if red == false then
  66. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  67. return
  68. end
  69.  
  70. local res, err = red:llen(mymailbox)
  71. if err ~= nil then
  72. ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
  73. return
  74. end
  75.  
  76. if res == then
  77. res, err = red:brpop(mymailbox, )
  78. ngx.print('[')
  79. for k, v in ipairs(res) do
  80. if k == then
  81. ngx.print(v)
  82. end
  83. end
  84. ngx.print(']')
  85. else
  86. if res > then
  87. res =
  88. end
  89. local i =
  90. ngx.print('[')
  91. for i=, res - , do
  92. local msg, _ = red:rpop(mymailbox)
  93. ngx.print(msg)
  94. if i ~= res - then
  95. ngx.print(',')
  96. end
  97. end
  98. ngx.print(']')
  99. end
  100. ngx.exit(ngx.HTTP_OK)

nginx-lua实现简单权限控制的更多相关文章

  1. NGINX + LUA实现复杂的控制

    安装lua_nginx_module 模块 lua_nginx_module 可以一步步的安装,也可以直接用淘宝的OpenResty Centos和debian的安装就简单了.. 这里说下freebs ...

  2. nginx+lua实现简单的waf网页防火墙功能

    原文:http://www.2cto.com/net/201608/534272.html 安装LuaJIT http://luajit.org/download/LuaJIT-2.0.4.tar.g ...

  3. NGINX + LUA实现复杂的控制 --源自http://outofmemory.cn/code-snippet/14396/nginx-and-lua

    安装lua_nginx_module 模块 lua_nginx_module 可以一步步的安装,也可以直接用淘宝的OpenResty Centos和debian的安装就简单了.. 这里说下freebs ...

  4. nginx+lua构建简单waf网页防火墙

    需求背景 类似于论坛型的网站经常会被黑掉,除了增加硬件防护感觉效果还是不太好,还会偶尔被黑,waf的功能正好实现了这个需求. waf的作用: 防止sql注入,本地包含,部分溢出,fuzzing测试,x ...

  5. 通过lua进行nginx的权限控制

    nginx_lua的安装 nginx使用luajit进行编译安装 使用openresty进行yum安装 openresty中将lua和nginx进行封装,详情可查看openresty官网 openre ...

  6. 使用nginx和iptables做访问权限控制(IP和MAC)

    之前配置的服务器,相当于对整个内网都是公开的 而且,除了可以通过80端口的nginx来间接访问各项服务,也可以绕过nginx,直接ip地址加端口访问对应服务 这是不对的啊,所以我们要做一些限制 因为只 ...

  7. shiro权限控制的简单实现

    权限控制常用的有shiro.spring security,两者相比较,各有优缺点,此篇文章以shiro为例,实现系统的权限控制. 一.数据库的设计 简单的五张表,用户.角色.权限及关联表: CREA ...

  8. webapi框架搭建-安全机制(三)-简单的基于角色的权限控制

    webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...

  9. 简单的RBAC用户角色权限控制

    Java web项目中,无论项目是大是小,或多或少都会涉及到用户访问权限的控制,权限管理总体的设计思路就是,不该看的不看,不该做的不做!据我目前的了解,我所知道的几种实现访问权限控制的方式有: JQu ...

随机推荐

  1. IO库 8.5

    题目:重写8.4中的函数,将每一个单词作为一个独立的元素进行存储. #include <iostream> #include <fstream> #include <st ...

  2. php ZIP压缩类实例分享

    php ZIP压缩类实例分享 <?php $zipfiles =array("/root/pooy/test1.txt","/root/pooy/test2.txt ...

  3. 这两天写的mybatis配置文件,主要是有输出和输入的存储过程

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...

  4. Yii2.0中文开发向导——自定义日志文件写日志

    头部引入log类use yii\log\FileTarget; $time = microtime(true);$log = new FileTarget();$log->logFile = Y ...

  5. Fedora 19下Guacamole的安装使用

    由于我要使用RDP实现web远程桌面,因此需要用到了Guacamole这个开源的软件.之前用Ubuntu12.04折腾了一晚上,也没有找到依赖库文件,而Guacamole的官方安装说明却没有介绍这个依 ...

  6. 转:CI伪静态化

    去掉php框架CI默认url中的index.php 2010-03-17 17:33:07|  分类: php框架ci |字号 订阅   CI默认的rewrite url中是类似这样的,例如你的CI根 ...

  7. HDU 5730 Shell Necklace(CDQ分治+FFT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...

  8. MySQL性能调优的方法

    第一种方法 1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的 性能,我们可以将表中字 ...

  9. String、StringBuffer和StringBuild的区别

    public class Test1 { public static void stringReplace (String text) { text = text.replace('j','i') ; ...

  10. linux 使用ssh到远端并且使用while的坑

    如果要使用ssh批量登录到其它系统上操作时,我们会采用循环的方式去处理,那么这里存在一个巨大坑,你必须要小心了. 现在是想用一个脚本获取远程服务器端/root下面的文件: #!/bin/bash ca ...