[入门]使用Openresty构建认证网关

lwhile关注
0.5092017.10.07 16:00:03字数 1,330阅读 4,112

在单体应用中, 我们可以通过 cookie + session, 或者 JSON web token, 将认证逻辑在单体应用中实现, 简单高效, 还特别省事.

然而这几年随着服务化潮流越来越火(我觉得这是必然趋势, 想想我们人类社会是如何运作的), 很多以前单体应用不存在的问题, 现在已成为对单体应用拆分过程中的第一个障碍, 比如系统的认证体系.

如果每个拆出来的服务都要做一次认证(就是程序员多写几份认证的代码啦), 对于有理想有追求的灵魂の码农来说, 是绝对无法接受的.你说认证代码copy就好了, 不用重新写.no no no, 这样搞出来的架构不仅看着别扭, 代码闻着就觉得臭, 而且迟早有一天会出问题.

解决单体应用拆分服务后的认证问题其实很常规, 回想下祖师爷们帮我们总结的一句话: "Any problem in computer science can be solved by another layer of indirection." 我们可以在所有服务前面增加一层认证服务.

 
Paste_Image.png

看到认证服务这一层用来作为用户请求的总入口, 有Nginx或者Apache使用经验的同学自然而然就想到它们. 如果能把认证模块的功能整合进Nginx或者Apache这些Web服务器, 那岂不是更完美 ?

而这篇文章的主角: Openresty,就可以帮助我们简单快速得完成这个想法.这是一个由春哥(Github)发起的项目.你可以将Openresty看做Nginx + 常用模块构成的软件包, 但是最重要的功能是我们可以使用Lua在Nginx实现Web框架才能实现的逻辑, 接下来文章将会开始介绍如何使用Openresty, 将上面提到的认证服务整合进Nginx里.

安装

Openresty有两种安装方式, 一种是使用源码编译安装.一种使用官方提供的预编译包:
具体可参考官网的安装文档

Hello world

如果你没修改过Openresty的安装位置, 默认会被安装在/use/local/openresty目录下.我们现在可以尝试写一个Hello world级别的demo.

为Openresty创建工作目录并创建配置文件:

mkdir ~/openresty_work
cd ~/openresty_work
touch nginx.conf

接下来在nginx.conf里面配置一个路由规则

worker_processes 1;
error_log logs/error.log; events {
worker_connections 1024;
} http {
server {
listen 8080;
location /hello {
default_type text/html;
content_by_lua_block {
ngx.say("Hello Openresty.")
}
}
}
}

跟普通的Nginx配置文件比起来, 上面的配置多了一个content_by_lua_block指令, 正是通过调用该指令, 访问该路由的时候,才会输出相应的内容.这个指令是由Openresty中的LuaNginxModule模块提供的功能, 请求进来的时候, Nginx会启动lua的虚拟机, 输出的内容则由lua提供.

我们可以使用content_by_lua_file指令替代content_by_lua_block, 将相关的lua代码写进文件里.

location /hello {
content_by_lua_file lua/hello.lua;
}
--- hello.lua
ngx.say("Hello Openresty.")

有了上面的铺垫,接下来可以开始构建我们的认证服务,认证的方式使用JWT

Openresty将一个请求的生命周期划分为4个阶段:

 
Paste_Image.png

我们的认证服务将会挂载在第二阶段, 即 Rewrite/Access Phase 上.

接下来准备一个需要用到的库:
lua-resty-jwt
clone下来后放到hello.lua文件所在的文件夹,并将lua_package_path配置为:

lua_package_path "/root/openresty_work/lua/?.lua;/root/openresty_work/lua/lua-resty-jwt/lib/?.lua;;";

构建的思路也很简单, 对用户提供一个登录请求, 验证身份后将jwt token分发给用户.用户接下来访问需要认证的接口, 则在header里面加入该token, 请求进入Openresty后由lua提取出token进行认证.

Nginx配置文件

server {
listen 8080;
location /hello {
content_by_lua_file lua/hello.lua;
}
location /login {
content_by_lua_file lua/sign.lua;
}
location /service1 {
access_by_lua_file lua/verify.lua;
# 需要反向代理在这配置
}
location /service {
access_by_lua_file lua/verify.lua;
# ...
}
}

下面是配置中相关的lua文件
sign.lua ↓:

local jwt = require 'resty.jwt'

-- 只允许POST请求
if ngx.req.get_method() ~= 'POST' then
ngx.status = 405
ngx.say("Mehtod Not Allow")
return
end -- 获取请求body
ngx.req.read_body()
local body_raw = ngx.req.get_body_data()
local body_json = cjson.decode(body_raw)
local username = body_json['username']
local password = body_json['password'] if not username or not password then
ngx.log(ngx.ERR, username, password)
ngx.status = 400
ngx.say('无法获取账号或者密码')
return
end -- 验证账号和密码是否正确,如果验证失败则做如下处理
if not this_is_a_auth_method(username, password) then
ngx.status = 401
ngx.say('认证失败')
return
end

verify.lua ↓:

local jwt = require 'resty.jwt'

-- 从请求中提取header并从header从获取token字段
local headers = ngx.req.get_headers()
local token = headers['token'] -- 检查token是否存在
if not token then
ngx.status = 400
ngx.say('无法获取token')
return
end -- 验证token
local jwt_obj = jwt:verify(vars.jwt_salt(), token)
if not jwt_obj['verified'] then
ngx.status = 401
ngx.say('无效的token')
return
end

至此一个使用Openresty构建的认证网关的雏形已经出来了.需要说明的一句是, 上面的代码由于没有公司相关的运行环境,笔者没有经过测试和验证.所以只可阅读,不可复制后直接运行 :)

如果想把这套认证网关用在生产环境上, 还有很多东西需要考虑.比如跨域问题, 静态文件的代理问题等等.

个人接触Openresty的时间也不长, 文中难免会有地方写错了或者表达得很差, 欢迎发评论或者发邮件给我指正: lwhile521@gmail.com ,感谢.

对于Openresty, 个人认为要对它产生兴趣,关键在于认不认可让Nginx承担除了Web服务器之外更多的业务, 对于Openresty, 它能带来的好处有:

  1. 极致的性能.上文没有提到Openresty的性能, 其实Openresty的编程模型和NodeJS很像, 在Openresty的世界里面,所有东西都是非阻塞的,更难得可贵的是, 它不需要使用NodeJS中的回调函数, 代码写起来其实还是同步模型, 配合C语言编写的Nginx, 最快的脚本语言lua+luajit解释器,这套方案的性能无可挑剔了.

  2. 降低了Nginx模块的开发难度. Nginx + C/C++能做的, Openresty用lua都能做.开发效率高了, 性能还不怎么降, 何乐而不为呢?

使用Openresty构建认证网关的更多相关文章

  1. SpringCloud学习笔记(6):使用Zuul构建服务网关

    简介 Zuul是Netflix提供的一个开源的API网关服务器,SpringCloud对Zuul进行了整合和增强.服务网关Zuul聚合了所有微服务接口,并统一对外暴露,外部客户端只需与服务网关交互即可 ...

  2. Openresty最佳案例 | 第9篇:Openresty实现的网关权限控制

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616779 本文出自方志朋的博客 简介 采用openresty 开发出的api网关有很多 ...

  3. 使用springcloud zuul构建接口网关

    一  微服务网关背景及简介 不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求.比如一个电影购票的收集APP,可能回调用电影分类微服务,用户微服务,支付微服 ...

  4. RouteOS软路由HotSpot热点认证网关

    实现要求: 实现局域网有线无线需在网页输入用户名和密码登录,不同用户登录有不同的访问内外网权限. 环境要求: 一台PC机安装三张网卡,第一张网卡连接外网,第二张网卡配置局域网,第三张网卡做配置连接使用 ...

  5. RouteOS软路由HotSpot热点认证网关添加白名单和黑名单

    1.添加白名单和黑名单地址池 白名单IP地址池 172.18.10.0/24 黑名单IP地址池 172.18.20.0/24 2.添加IP网关 白名单网关 172.18.10.0/24 黑名单网关 1 ...

  6. apisix 基于openresty 的api 网关

    apisix 是由openresty 团队开发并开源的微服务api gateway,还不错,官方文档也比较全,同时这个也是一个不错的学习openresty 的项目 以下为来自官方的架构图 插件加载 插 ...

  7. asp.net core系列 60 Ocelot 构建服务认证示例

    一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...

  8. OpenResty api 网关

    1,Orange网关 Orange是一个基于OpenResty的API网关.除Nginx的基本功能外,它还可用于API监控.访问控制(鉴权.WAF).流量筛选.访问限速.AB测试.动态分流等.它有以下 ...

  9. AspNetCore微服务下的网关-Kong(一)

    Kong是Mashape开源的高性能高可用API网关和API服务管理层.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kong在Mashape 管理了超过15,000 个A ...

随机推荐

  1. java中执行cmd命令

    一.java执行cmd命令的三种方式:http://www.jb51.net/article/80829.htm 参考:https://www.cnblogs.com/zhufu9426/p/7928 ...

  2. 干!垃圾微软!发布我的Netcore跨平台UI框架 CPF

    什么鬼,我的CPF快写好了,你居然也要搞跨平台UI框架?什么Maui? 之前怎么不早说要搞跨平台UI框架呢?看到谷歌搞flutter眼红了?明年年底发布?又搞这种追别人屁股的烂事情. 什么MVU模式? ...

  3. 生日聚会Party——这个线性dp有点嚣张

    题目描述 今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party. hidadz带着朋友们来到花园中,打算 坐成一排玩游戏.为了游戏不至于无聊,就座的方案应满足如下条件:对于任意连续 ...

  4. 安卓移动端line-height垂直居中出现偏移的原因,及解决方法

    目前在移动端安卓手机上使用line-height属性,让它的值等于height,结果发现是不居中的.出现了一定位置的偏移情况,如果略微只有两三个像素差距是看不出来的. 左图中的字号是12px,右图中的 ...

  5. 自适应高度输入框(contenteditable/textarea)

      一.用div模拟textarea div模拟输入域可以根据输入内容自动伸缩,而input和textarea输入内容较多时,高度固定,内容会显示不全. 1.坑1(IOS端无法输入) 在取消全局默认样 ...

  6. SpringCloud系列之集成分布式事务Seata应用篇

    目录 前言 项目版本 项目说明 Seata服务端部署 Seata客户端集成 cloud-web module-order module-cart module-goods module-wallet ...

  7. Blazor带我重玩前端(三)

    写在前面 需要升级VS2019以及.NET Core到最新版(具体的最低支持,我已经忘了,总是越新支持的就越好),以更好的支持自己开发Blazor项目. WebAssembly 搜索Blazor模板 ...

  8. php 修改图片大小

    <?php set_time_limit(0);ini_set("memory_limit","500M");$dir = dir('./');while ...

  9. PE解析器与加载器编写指南

    PE解析器与加载器编写指南 最近准备去实习,看公司要求应该开发PE相关的查杀引擎,因此再回头复习一下PE格式,重新写一个PE解析器和PE加载器,再此记录下有关坑. PE解析器部分: 1)如何确定节区表 ...

  10. java 面向对象(二十七):注解的使用

    1. 注解的理解① jdk 5.0 新增的功能*② Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理.通过使用 Annotation, ...