之前使用了openresty进行了rsa跟aes的加解密测试。现在我们整合一下、使用openresty连接redis做鉴权、解密。之前提到过,我们不使用cookie而是使用token来认证用户信息。而且token是我们自己加密的、加密的规则就是使用aes进行加密。我们再来缕一缕整个流程。

客户端(浏览器)流程:

第一步:先获取token(临时token),返回的token是aes加密的,这里的密钥我们就使用固定的aes密钥就好了。token里面包含userId跟tokenId,我们使用tokenId来做我们缓存的key;

第二步:获取rsa公钥,这里必须带上token才能去获取rsa密钥对;

第三步:客户端(浏览器)每进入一个页面(或者每次请求)随机生成aes密钥,使用该密钥对请求体加密;

第四步:客户端(浏览器)在发送请求之前,将随机生成的aes密钥使用rsa公钥加密,并写入当前请求的请求头中;

openresty鉴权+解密流程

第一步:获取请求token,并对token进行解密,使用aes与java后端约定好的密钥;

第二步:从redis(存储之前的文章有介绍)获取用户信息,做登录认证,循环角色编码+uri做鉴权;

第三步:从redis中获取与客户端对应的私钥,解密客户端随机生成的aes密钥;

第四步:使用客户端的aes密钥解密客户端请求体内容;

代码

大致的流程就是这样了、接下来我们看看实现的代码跟测试的效果。

redisUtil.lua(需要放在lualib\resty目录下)

local U_ = {_VERSION='1.0.0'}
function U_.keepalive(redis)redis:set_keepalive(1000, 200)
end
function U_.connectRedis(redis)redis:set_timeouts(1000, 1000, 1000)local ok, err = redis:connect("127.0.0.1", 6379)if not ok thenngx.exit(601)returnend-- 设置密码local ok, err = redis:auth("redis密码")if not ok thenngx.exit(602)returnend
end
function U_.getRedisKey(redis,key)local res, err = redis:get(key)if not res thenreturn ngx.nullendreturn res
end
return U_

nginx配置

server {listen 6378;location /redis {default_type text/html;content_by_lua_file lua/gateway.lua;}
}

gateway.lua

local nowUri = string.gsub(ngx.var.uri, "/", "-")
ngx.say("请求的URI:",nowUri)
local headers = ngx.req.get_headers()
local token = headers["token"]
if token == nil or token == ngx.null or token == '' then --ngx.exit(403)ngx.say("获取不到token信息")return
end
-- AES使用固定的key跟向量解密token
local key = "569d874ds63219ds"
local iv = "dsfd985s6d7yfd54"
local aes = require "resty.aes"
local aes_128_cbc_with_iv = assert(aes:new(key,nil, aes.cipher(128,"cbc"), {iv=iv}))
local cipherBytes = ngx.decode_base64(token)
local tokenText, err = aes_128_cbc_with_iv:decrypt(cipherBytes)
ngx.say("token解密结果:",tokenText)
if not tokenText then--ngx.exit(403)ngx.say("token解密失败:",err)return
end
if tokenText == nil or tokenText == ngx.null or tokenText == '' then--ngx.exit(403)ngx.say("token解密明文为空:",token)return
end
local userTokenKey = string.sub(tokenText,38,#tokenText)-- 连接redis
local redisClient = require "resty.redis"
local redis = redisClient:new()
local redisUtil = require "resty.redisUtil"
redisUtil.connectRedis(redis)-- 获取用户角色信息——认证
local userInfo = redisUtil.getRedisKey(redis,'user-info:'..userTokenKey)
ngx.say("用户角色:",userInfo)
if userInfo == nil or userInfo == ngx.null then-- 读取不到用户信息--ngx.exit(403)ngx.say("读取不到用户信息:",token)return
endlocal json = require("cjson")
local userInfoJson = json.decode(userInfo)
local roleList = userInfoJson.role
local authFlag = false
-- 循环匹配角色+uri鉴权
for i, v in ipairs(roleList) dolocal uriAuth = redisUtil.getRedisKey(redis,'auth-url:'.. v.roleCode .. ':' .. nowUri)if uriAuth ~= nil and uriAuth ~= ngx.null and tonumber(uriAuth) == 1 thenauthFlag = truebreakend
endif authFlag == false then-- 没有权限ngx.say("没有权限:",token)--ngx.exit(403)return
end-- 截取并拼接出redis存储的rsa私钥的key(注意不要有中文)
local redis_priv_key = 'rsa-key:' .. userTokenKey
ngx.say("rsa_priv_key:",redis_priv_key)
local rsa_priv_key = '-----BEGIN PRIVATE KEY-----\n' .. redisUtil.getRedisKey(redis,redis_priv_key) .. '\n-----END PRIVATE KEY-----'
-- 关闭redis连接
redisUtil.keepalive(redis)
ngx.say(rsa_priv_key)-- RSA解密:客户端AES密钥
local resty_rsa = require "resty.rsa"
local service_priv, service_err = resty_rsa:new({ private_key = rsa_priv_key ,key_type = resty_rsa.KEY_TYPE.PKCS8,padding = resty_rsa.PADDING.RSA_PKCS1_OAEP_PADDING
})
if not service_priv thenngx.say("创建私钥错误: ", service_err)--ngx.exit(500)return
end
local pub_pass_str = headers["passkeys"]
ngx.say("客户端aes密钥密文: ", pub_pass_str)
-- 使用java生成的私钥、解密客户端使用公钥加密的密文
local service_priv_de = service_priv:decrypt(ngx.decode_base64(pub_pass_str))
ngx.say("客户端aes密钥明文: ", service_priv_de)
local client_aes_key = string.sub(service_priv_de,0,16)
local client_aes_iv = string.sub(service_priv_de,18,33)
ngx.say("客户端aes key: ", client_aes_key)
ngx.say("客户端aes iv: ", client_aes_iv)
local aes_cbc_client = assert(aes:new(client_aes_key,nil, aes.cipher(128,"cbc"), {iv=client_aes_iv}))
ngx.req.read_body()
local req_body = ngx.req.get_body_data()
ngx.say(req_body)local req_body_json = json.decode(req_body);
local de_body_text = ngx.decode_base64(req_body_json.text)
local body_text, _body_err = aes_cbc_client:decrypt(de_body_text)
ngx.say("body解密结果:",body_text)

redis数据

        用户

        私钥 (跟之前加密篇的一致)

         权限(固定前缀:角色编码:uri——uri中的/被替换成-)

测试

使用postman发送测试请求

请求头:

token:PGpgSf1e6ZfD8tzTnHUr4WO8JCNi6GeZE+WP9FfA/rdZRAeFp1Kan8FOVrf0D9FHLIQpMGfKY075EEichxlytedD4Y2zVE7xRJQL0ejnxj4=
passkeys:Z7W7qJhA+rj/qxDkT3Yr3u6GkoAg88q9Ct5IurQUdwqEJGrBx172Pez8js1mnpekiFljdkhb96+JyKi8odhIXkNGEFMcSYoLBFxyQK3wzcpdzm1RXEvmSHmGLsgMTebWlIFiZnfC7PnKaxS3EF/omHmYt9IQBEqN6XAHVE6IB9K4TPGvoraPGbzJqdMr4D6CYZ2KsKKgdyjBOUJMN9UrKCvcuruXwknOXV4i8R46XwM9g8YcAH8Hfmujo07YDVicxy5dWTS3/M56zzSbeTIv67lENeiSSygtKAcrIZF+dRM6NAULckoyPAsD7SWX68AGql4dxS1fQw7EpWZTRvkaMA==

请求体:

{

"text":"iyAuevH2ik9Ld6JxJDXYw0vxj0s4YL9EtqQ8OzsZmY+U6ggQ4kWxTlVDc/rpSefYBFO/gK+epvF/nWQsh6HTRNxpnDbwFwiEXFXLIuXFjHo="

}

结果:

请求的URI:-redis-test
token解密结果:12d57406-28aa-41f5-818d-6521e44949bd@e086a63d-196c-4b3e-9aa4-768f7d51cf52
用户角色:{"userName":"administrator","age":18,"sex":"男","idCard":"668","role":[{"roleName":"超级管理员","roleCode":"root"},{"roleName":"测试","roleCode":"test"},{"roleName":"普通管理员","roleCode":"admin"}]}
rsa_priv_key:rsa-key:e086a63d-196c-4b3e-9aa4-768f7d51cf52
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCM56VH633AAvZ
/SzfFkByba6fVx6ClCx1KZe90PQyZ8uSuxUBdmXZBzdXg/R1u2h6GqhCT7Uvnxu
UN+xxPnJbCn6DtM/5tDA3IJV/aWA67eQr9lZBvvjrLeBu3huAC0EldojX0FQBnV
2tPTHiJpMDkWhLgDeGVVUZTQfWhxVvnAuAxzeiwi/pfGs5wzCI0kzF8q8xGjo83
7hv5ccAmdSNenWal+c4XcKTkiWZyExAAnmdxEL0NQSSvg1cHa4NPfqRJTqfFFHy
/1TlA7jE1GNga2AUc/DDrDfRl4c0qI6nb9xOkh1KNqEkJ8S5cneG04ds7z+IzIr
eWw8dnCsghh2vBAgMBAAECggEASH1T9rAcPZBIqCxWQPlm/j5gVgchikcxhnjyu
+Y8eWcQZylrd7vfrvLqOZl+bu0gDz+mz7Og/VjBtnOdmQeCOBZPgDjjh85PuMwh
h/8NdT1MfjFX4WUIcm0UNVLaJBhr5hPxleTIFGJQ/rbkvEtaQSBl3YbGq0D3sRW
Z/OO/6BQ7PhVWMsqexAbgKQU3MhCoZoURovffdbxhNJQiOR2oQnf31+4MV6f8QV
2UTCvhsb2Z8ybXMCJGUssRkSud2rkOB+T1/vqDOADEdo6Srozlq4iQ7FgbyApsF
9G1ZEjF8L0AC+9eCZSivYvTJceqO9/KHSJtBhnm7hFz2EMVi7ZPwQKBgQC/ScXb
lSuMASwGuWnU2kWIrsy3h7R/PqfeN4AjeIWZGOIkjrQQ0l+y1HjRW3aJ5yWqtsP
Yf2y+t/+7h3tLZ8AS4UrJTgRV3p/cBOD6GGfjOfdAxCpcaofwwl8ZA4CXMUxbbJ
UogQHnmAwfBPlkH2YUcfpS+ZuuZVsHYgBD8rsNPQKBgQC8koBZlLv9JyFgmz/rk
ABBJy6u4Th/spn7qYuiWXGMo/EPAdDeTQVf750/8bV5kv4hZysCz8j9isYtvGYR
CuRvcaaGBjMIJ7sV7YTHH9phoon+Gzf/kUWQslFupWu/9Dv60Nb3iOD26oKfBFf
NhlfczPVXhQnttQkgZ8GM+CGI1QKBgBkcOw/fHg9L3Bap4j2hxXzyzUbOVqBZfj
nKeVSuroLxZEY+QV7v7sYP5Cg/ZGkn4abuRPk3iPPkPXrFhybX4LvZvTJ9vk3zY
nLEZTAPYhvO8SkcVx84kM3HBirHberq+sYJk+70OGbJa9Xqlj5RbNoEOEMKJyiW
f4ORls1UoL9VAoGAHIF8+427WUp4BjWR1RdAopi8utz7AHrMQjngDNu+iYci4qT
goSo9fMIpIEh2qXkqB3ykCNnGRWWcDb/kIgFmhN5GUQ5Q2pO++VKddsh+57F9cL
dGoNCiFnyOSM6i2jKeeozlYigD8e+DbWxnpX8AezVUhTVsSc3LImXs4VWFJD0Cg
YBQPpWmlcij6zD1Qdgb6X6YcZBI/vfwQO8LoDerr6AwJImwHswHz7gENCeT99ZN
IORX+wKRutMHSLiIFIw3XGpkg1cp3m4hHvdDsLIGIWZaIQBDEMOOdRsDGKDBl9R
GpwEUgsRssMuVjOHRijicIA86yu3wzP6sO+7ttHCnBO8Aig==
-----END PRIVATE KEY-----
客户端aes密钥密文:
Z7W7qJhA+rj/qxDkT3Yr3u6GkoAg88q9Ct5IurQUdwqEJGrBx172Pez8js1mnpekiFljdkhb96+JyKi8odhIXkNGEFMcSYoLBFxyQK3wzcpdzm1RXEvmSHmGLsgMTebWlIFiZnfC7PnKaxS3EF/omHmYt9IQBEqN6XAHVE6IB9K4TPGvoraPGbzJqdMr4D6CYZ2KsKKgdyjBOUJMN9UrKCvcuruXwknOXV4i8R46XwM9g8YcAH8Hfmujo07YDVicxy5dWTS3/M56zzSbeTIv67lENeiSSygtKAcrIZF+dRM6NAULckoyPAsD7SWX68AGql4dxS1fQw7EpWZTRvkaMA==
客户端aes密钥明文: 6zUwU5McVrZdkKMs@vpgmUFeRd9Ms5o7G
客户端aes key: 6zUwU5McVrZdkKMs
客户端aes iv: vpgmUFeRd9Ms5o7G
{
"text":"iyAuevH2ik9Ld6JxJDXYw0vxj0s4YL9EtqQ8OzsZmY+U6ggQ4kWxTlVDc/rpSefYBFO/gK+epvF/nWQsh6HTRNxpnDbwFwiEXFXLIuXFjHo="
}
body解密结果:{"userName":"administrator","passWord":"Xts@#!$8965...dTT","type":"pass"}

openresty 网关rsa+aes+redis鉴权解密相关推荐

  1. RSA+AES数字信封加解密设计

    登录认证.鉴权这些都做好了过后.就开始我们的加密设计了.这里采用了简化数字信封进行加密.首先客户端(浏览器)先请求一份RSA非对称密钥.如果我们采用了openresty或者有能力在nginx开发C模块 ...

  2. 华为光猫鉴权解密逆向

    hw_ctree.xml里面的pppoe.voip等鉴权密码被加密了.有$1$2两种算法. 加解密的函数位于libhw_ssp_ssl.so HW_OS_AESDecrypt(char *src, i ...

  3. 单点登录解决方案--网关、认证、鉴权

    总流程 1)用户访问 http://localhost:8001/api/oauth/toLogin 先过网关,网关相当于门卫.网关看你的uri,/api/oauth/toLogin,直接放行.去登录 ...

  4. 微服务网关限流鉴权-wei-fu-wu-wang-guan-xian-liu--jian-quan

    title: 微服务网关限流&鉴权 date: 2022-01-06 14:40:45.047 updated: 2022-01-06 14:40:45.047 url: https://ww ...

  5. 微服务网关鉴权:gateway使用、网关限流使用、用户密码加密、JWT鉴权

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...

  6. 微服务网关鉴权——gateway使用、网关限流使用、用户密码加密、JWT鉴权

    文章目录 微服务网关鉴权 课程目标 1.微服务网关Gateway 1.1 微服务网关概述 1.2 微服务网关微服务搭建 1.3 微服务网关跨域 1.4 微服务网关过滤器 2 网关限流 2.1 思路分析 ...

  7. 微服务网关鉴权:gateway使用、网关限流使用 用户密码加密 JWT鉴权

    目标 掌握微服务网关Gateway的系统搭建 掌握网关限流的实现 能够使用BCrypt实现对密码的加密与验证 了解加密算法 能够使用JWT实现微服务鉴权 1.微服务网关Gateway 1.1 微服务网 ...

  8. 认证鉴权对于 API 网关的重要性

    认证鉴权作为 API 网关不可或缺的能力,已然成为用户在选型 API 网关时考量的重要因素之一. 作者钱勇,API7.ai 开发工程师,Apache APISIX Committer 在当下云原生越发 ...

  9. SpringCloud:Gateway之鉴权

    一.JWT 实现微服务鉴权 JWT一般用于实现单点登录.单点登录:如腾讯下的游戏有很多,包括lol,飞车等,在qq游戏对战平台上登录一次,然后这些不同的平台都可以直接登陆进去了,这就是单点登录的使用场 ...

  10. 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

最新文章

  1. 自动生成纯文本表格的工具
  2. python正则表达式re.sub用法
  3. FTP软件VSFTP配置文件详解
  4. ARM的cache和写缓冲器(write buffer)
  5. case when else 默认随机_SQL高级知识——CASE的用法
  6. LINUX静态网络配置
  7. spring-boot 之 使用Admin监控应用
  8. STM32F103_DDWG窗口看门狗
  9. 2019计算机调剂困难,2019年研究生调剂困难程度远超想象
  10. 语言怎么得到直流电压并采样_250V10A高频直流电源/大电流直流稳压稳流电源
  11. nginx集群,带负载均衡(监听多个端口),超详细,轮询分发
  12. 1656. Far Away Kingdom's Army
  13. Windows快捷键(三)—— 触摸板手势
  14. Python基础入门知识(2)
  15. css做八边形图片有边框
  16. 谷歌浏览器加载不了js_优化谷歌排名的必备技巧
  17. 前列腺穿刺活检技术发展
  18. 利率市场化冲击传统资产负债管理 金融壹账通助力银行科技转型
  19. 网易2018编程题之游历魔法王国
  20. Typora导出word文档自动生成目录

热门文章

  1. hitb2018_gundam —— tcache double free
  2. html缩小照片尺寸像素不变,怎么修改照片像素,但又不改变照片大小呢?——解决照片因大小无法上传的方案...
  3. iOS前后台切换和监听
  4. html自动弹图片,JS自动适应的图片弹窗实例
  5. 在已有win7系统的基础上重装win10系统
  6. ffmpeg从mp4(音视频)中提取音频aac
  7. 最小行走距离(dfs+虚树)
  8. python全栈测试开发工程师_Python测试开发全栈核心课程 互联网测试工程师必修课...
  9. 【数据结构】—— 树状数组
  10. 如何选拔人才-人力资源探讨