使用Openresty构建认证网关
[入门]使用Openresty构建认证网关
在单体应用中, 我们可以通过 cookie + session, 或者 JSON web token, 将认证逻辑在单体应用中实现, 简单高效, 还特别省事.
然而这几年随着服务化潮流越来越火(我觉得这是必然趋势, 想想我们人类社会是如何运作的), 很多以前单体应用不存在的问题, 现在已成为对单体应用拆分过程中的第一个障碍, 比如系统的认证体系.
如果每个拆出来的服务都要做一次认证(就是程序员多写几份认证的代码啦), 对于有理想有追求的灵魂の码农来说, 是绝对无法接受的.你说认证代码copy就好了, 不用重新写.no no no, 这样搞出来的架构不仅看着别扭, 代码闻着就觉得臭, 而且迟早有一天会出问题.
解决单体应用拆分服务后的认证问题其实很常规, 回想下祖师爷们帮我们总结的一句话: "Any problem in computer science can be solved by another layer of indirection." 我们可以在所有服务前面增加一层认证服务.
看到认证服务这一层用来作为用户请求的总入口, 有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个阶段:
我们的认证服务将会挂载在第二阶段, 即 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, 它能带来的好处有:
极致的性能.上文没有提到Openresty的性能, 其实Openresty的编程模型和NodeJS很像, 在Openresty的世界里面,所有东西都是非阻塞的,更难得可贵的是, 它不需要使用NodeJS中的回调函数, 代码写起来其实还是同步模型, 配合C语言编写的Nginx, 最快的脚本语言lua+luajit解释器,这套方案的性能无可挑剔了.
降低了Nginx模块的开发难度. Nginx + C/C++能做的, Openresty用lua都能做.开发效率高了, 性能还不怎么降, 何乐而不为呢?
使用Openresty构建认证网关的更多相关文章
- SpringCloud学习笔记(6):使用Zuul构建服务网关
简介 Zuul是Netflix提供的一个开源的API网关服务器,SpringCloud对Zuul进行了整合和增强.服务网关Zuul聚合了所有微服务接口,并统一对外暴露,外部客户端只需与服务网关交互即可 ...
- Openresty最佳案例 | 第9篇:Openresty实现的网关权限控制
转载请标明出处: http://blog.csdn.net/forezp/article/details/78616779 本文出自方志朋的博客 简介 采用openresty 开发出的api网关有很多 ...
- 使用springcloud zuul构建接口网关
一 微服务网关背景及简介 不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求.比如一个电影购票的收集APP,可能回调用电影分类微服务,用户微服务,支付微服 ...
- RouteOS软路由HotSpot热点认证网关
实现要求: 实现局域网有线无线需在网页输入用户名和密码登录,不同用户登录有不同的访问内外网权限. 环境要求: 一台PC机安装三张网卡,第一张网卡连接外网,第二张网卡配置局域网,第三张网卡做配置连接使用 ...
- RouteOS软路由HotSpot热点认证网关添加白名单和黑名单
1.添加白名单和黑名单地址池 白名单IP地址池 172.18.10.0/24 黑名单IP地址池 172.18.20.0/24 2.添加IP网关 白名单网关 172.18.10.0/24 黑名单网关 1 ...
- apisix 基于openresty 的api 网关
apisix 是由openresty 团队开发并开源的微服务api gateway,还不错,官方文档也比较全,同时这个也是一个不错的学习openresty 的项目 以下为来自官方的架构图 插件加载 插 ...
- asp.net core系列 60 Ocelot 构建服务认证示例
一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...
- OpenResty api 网关
1,Orange网关 Orange是一个基于OpenResty的API网关.除Nginx的基本功能外,它还可用于API监控.访问控制(鉴权.WAF).流量筛选.访问限速.AB测试.动态分流等.它有以下 ...
- AspNetCore微服务下的网关-Kong(一)
Kong是Mashape开源的高性能高可用API网关和API服务管理层.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kong在Mashape 管理了超过15,000 个A ...
随机推荐
- Docker入门(1):概述
1.摘要 在这篇文章中,我将介绍一下为什么需要虚拟化的环境. 然后我将介绍耳熟能详的虚拟化技术:虚拟机,并大致的介绍一下虚拟机的原理,希望能够让你知道虚拟机的优劣. 在之后,针对虚拟机存在的问题,引出 ...
- MongoDB快速入门教程 (1)
1.MongoDB初识 1.1.MongoDB是什么? MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于 ...
- 实现客户端与服务端之间传输json数据
步骤:创建数据库,并创建表.利用myeclipse创建新工程,利用JDBC实现java操纵数据库.实现客户端类,服务端类.具体实现:创建数据表create table usertable( usern ...
- 如何解决TOP-K问题
前言:最近在开发一个功能:动态展示的订单数量排名前10的城市,这是一个典型的Top-k问题,其中k=10,也就是说找到一个集合中的前10名.实际生活中Top-K的问题非常广泛,比如:微博热搜的前100 ...
- Java 从入门到进阶之路(二十八)
在之前的文章我们都是通过 Java 在内存中应用,本章开始我们来看一下 Java 在系统文件(硬盘)上的操作. 系统文件就是我们电脑中的文件,简单来说就是像 Windows 系统中 C D E 等各类 ...
- js的几个小问题
1.存一个有效期为7天的cookie,key = nickname, val = Ace 代码: function setCookie(key,val,expires){ let now=new Da ...
- Fiddler和JMeter测试需要主要的地方
Fiddler里面设置请求头的时候ContentType和Content-Type这两种写法都可以: 这两种写法都可以. 但是在JMeter中必须要用Content-Type才行,如下图所示: (完)
- .netcore 网站启动后 502.5
网站启动后,报错 HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure 请检查安装的.netcore runtime版本和hosting版本是否 ...
- 关于WebServices的调用
1.使用soapui测试接口是否能通 具体操作步骤请查看:https://www.cnblogs.com/BINDAI/p/13201513.html Soapui请求结果集 2.获得soapu ...
- css中line-height的理解_介绍line-height实际应用
一.line-height的定义 css中line-height行高是指文本行基线之间的距离,不同字体,基线位置不同.line-height只影响行内元素和其他行内内容,而不会直接影响块级元素,如果块 ...