资讯专栏INFORMATION COLUMN

根据JWT的key和URL决定是否缓存HTTP请求

binaryTree / 3381人阅读

摘要:链接需求根据的和决定是否缓存请求比如里然后请求如果和一样,则缓存,否则不缓存解决方案使用基于的高性能缓存服务器

链接 https://stackoverflow.com/que...

需求

根据JWT的key和URL决定是否缓存HTTP请求

比如JWT里

payload: {
  "iss": "iss",
  "sub": "sub",
  "userGroupID": "{userGroupID}"
}

然后请求 https://myapi.example.com/gro...{groupID}/cars

如果 userGroupID和groupID一样,则缓存,否则不缓存

解决方案

使用 https://github.com/jiangwenyu... 基于HAProxy的高性能缓存服务器

1. Download and build, you will need lua

wget https://github.com/jiangwenyuan/nuster/releases/download/v1.8.8.2/nuster-1.8.8.2.tar.gz

make TARGET=linux2628 USE_ZLIB=1 USE_OPENSSL=1 USE_LUA=1 LUA_LIB=/opt/lua-5.3.1/lib LUA_INC=/opt/lua-5.3.1/include

2. create lua script, say, jwt_group_match.lua

 
-- base64 FROM http://lua-users.org/wiki/BaseSixtyFour

local b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

function dec(data)
    data = string.gsub(data, "[^"..b.."=]", "")
    return (data:gsub(".", function(x)
        if (x == "=") then return "" end
        local r,f="",(b:find(x)-1)
        for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and "1" or "0") end
        return r;
    end):gsub("%d%d%d?%d?%d?%d?%d?%d?", function(x)
        if (#x ~= 8) then return "" end
        local c=0
        for i=1,8 do c=c+(x:sub(i,i)=="1" and 2^(8-i) or 0) end
        return string.char(c)
    end))
end

-- end base64


-- json FROM https://gist.github.com/tylerneylon/59f4bcf316be525b30ab
json = {}


function kind_of(obj)
  if type(obj) ~= "table" then return type(obj) end
  local i = 1
  for _ in pairs(obj) do
    if obj[i] ~= nil then i = i + 1 else return "table" end
  end
  if i == 1 then return "table" else return "array" end
end

function escape_str(s)
  local in_char  = {"", """, "/", "", "f", "
", "
", "	"}
  local out_char = {"", """, "/",  "b",  "f",  "n",  "r",  "t"}
  for i, c in ipairs(in_char) do
    s = s:gsub(c, "" .. out_char[i])
  end
  return s
end

function skip_delim(str, pos, delim, err_if_missing)
  pos = pos + #str:match("^%s*", pos)
  if str:sub(pos, pos) ~= delim then
    if err_if_missing then
      error("Expected " .. delim .. " near position " .. pos)
    end
    return pos, false
  end
  return pos + 1, true
end

function parse_str_val(str, pos, val)
  val = val or ""
  local early_end_error = "End of input found while parsing string."
  if pos > #str then error(early_end_error) end
  local c = str:sub(pos, pos)
  if c == """  then return val, pos + 1 end
  if c ~= "" then return parse_str_val(str, pos + 1, val .. c) end
  -- We must have a  character.
  local esc_map = {b = "", f = "f", n = "
", r = "
", t = "	"}
  local nextc = str:sub(pos + 1, pos + 1)
  if not nextc then error(early_end_error) end
  return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))
end

function parse_num_val(str, pos)
  local num_str = str:match("^-?%d+%.?%d*[eE]?[+-]?%d*", pos)
  local val = tonumber(num_str)
  if not val then error("Error parsing number at position " .. pos .. ".") end
  return val, pos + #num_str
end

json.null = {}  -- This is a one-off table to represent the null value.

function json.parse(str, pos, end_delim)
  pos = pos or 1
  if pos > #str then error("Reached unexpected end of input.") end
  local pos = pos + #str:match("^%s*", pos)  -- Skip whitespace.
  local first = str:sub(pos, pos)
  if first == "{" then  -- Parse an object.
    local obj, key, delim_found = {}, true, true
    pos = pos + 1
    while true do
      key, pos = json.parse(str, pos, "}")
      if key == nil then return obj, pos end
      if not delim_found then error("Comma missing between object items.") end
      pos = skip_delim(str, pos, ":", true)  -- true -> error if missing.
      obj[key], pos = json.parse(str, pos)
      pos, delim_found = skip_delim(str, pos, ",")
    end
  elseif first == "[" then  -- Parse an array.
    local arr, val, delim_found = {}, true, true
    pos = pos + 1
    while true do
      val, pos = json.parse(str, pos, "]")
      if val == nil then return arr, pos end
      if not delim_found then error("Comma missing between array items.") end
      arr[#arr + 1] = val
      pos, delim_found = skip_delim(str, pos, ",")
    end
  elseif first == """ then  -- Parse a string.
    return parse_str_val(str, pos + 1)
  elseif first == "-" or first:match("%d") then  -- Parse a number.
    return parse_num_val(str, pos)
  elseif first == end_delim then  -- End of an object or array.
    return nil, pos + 1
  else  -- Parse true, false, or null.
    local literals = {["true"] = true, ["false"] = false, ["null"] = json.null}
    for lit_str, lit_val in pairs(literals) do
      local lit_end = pos + #lit_str - 1
      if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end
    end
    local pos_info_str = "position " .. pos .. ": " .. str:sub(pos, pos + 10)
    error("Invalid json syntax starting at " .. pos_info_str)
  end
end

-- end json






-- nuster jwt


function jwt_group_match(txn)

  local hdr = txn.http:req_get_headers()
  local jwt = hdr["jwt"]
  if jwt == nil then
    return false
  end

  _, payload, _ = jwt[0]:match"([^.]*)%.([^.]*)%.(.*)"
  if payload == nil then
    return false
  end

  local payload_dec = dec(payload)
  local payload_json = json.parse(payload_dec)


  if txn.sf:path() == "/group/" ..  payload_json["userGroupID"] .. "/cars" then
    return true
  end

  return false
end

core.register_fetches("jwt_group_match", jwt_group_match)

3. create conf, say, nuster.conf

global
    nuster cache on dict-size 1m data-size 100m
    debug
    lua-load jwt_group_match.lua

frontend web1
    bind *:8080
    mode http

    default_backend app1

backend app1
    mode http
    http-request set-var(req.jwt_group_match) lua.jwt_group_match

    nuster cache on
    nuster rule group if { var(req.jwt_group_match) -m bool }


    server s1 127.0.0.1:8000
    server s2 127.0.0.1:8001

3. start nuster

./haproxy -f nuster.conf

TEST

payload: {
  "iss": "iss",
  "sub": "sub",
  "userGroupID": "nuster"
}

curl http://127.0.0.1:8080/group/nuster/cars --header "jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3MiLCJzdWIiOiJzdWIiLCJ1c2VyR3JvdXBJRCI6Im51c3RlciJ9.hPpqQS0d4T2BQP90ZDcgxnqJ0AHmwWFqZvdxu65X3FM"

First run

[CACHE] To create

Second run

[CACHE] Hit

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/10743.html

相关文章

  • 根据JWTkeyURL决定是否缓存HTTP请求

    摘要:链接需求根据的和决定是否缓存请求比如里然后请求如果和一样,则缓存,否则不缓存解决方案使用基于的高性能缓存服务器 链接 https://stackoverflow.com/que... 需求 根据JWT的key和URL决定是否缓存HTTP请求 比如JWT里 payload: { iss: iss, sub: sub, userGroupID: {userGroupID} } ...

    wow_worktile 评论0 收藏0
  • dgate:an API Gateway based on Vert.x

    摘要:请注意闭包的返回值必需是。开发者可以利用相关方法来自定义其内容,会将闭包的返回值作为最终结果与其他后端服务的响应合并,然后返回给访问层。注意不要忘记本身是一个闭包否则,无法模拟过期后重新生成另一个的情况。 dgate:an API Gateway based on Vert.x dgate是基于Vertx的API Gateway。运行dgate的命令如下: java -jar dgat...

    dingding199389 评论0 收藏0
  • Koa-jwt 说明文档(机翻润色)

    摘要:机翻润色这个模块可以让你在你的应用中通过使用以下简称认证请求这个文档做了一个很好的介绍如果你使用版本同时你有一个低于版本的安装主分支仓库上的译者注上的版本使用所以必须是以上如果你使用你需要从安装这个代码在分支上安装用例认证中间件 KOA-JWT (机翻润色) node>=7.6.0 npm v3.2.2 这个模块可以让你在你的KOA应用中通过使用JSON WEB TOKEN(以下简称J...

    Cristic 评论0 收藏0
  • 基于Shiro,JWT实现微信小程序登录完整例子

    摘要:小程序官方流程图如下,官方地址如果此图理解不清楚的地方也可参看我的博客本文是对接微信小程序自定义登录的一个完整例子实现,技术栈为。调用微信接口获取和根据和自定义登陆态返回自定义登陆态给小程序端。 小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login....

    cfanr 评论0 收藏0
  • 分布式系统--感性认识JWT

    摘要:的安全性不好,攻击者可以通过获取本地进行欺骗或者利用进行攻击。 好久没写博客了,因为最近公司要求我学spring cloud ,早点将以前软件迁移到新的架构上。所以我那个拼命的学呐,总是图快,很多关键的笔记没有做好记录,现在又遗忘了很多关键的技术点,极其罪恶! 现在想一想,还是踏踏实实的走比较好。这不,今天我冒了个泡,来补一补前面我所学所忘的知识点。 想要解锁更多新姿势?请访问我的博客...

    sherlock221 评论0 收藏0

发表评论

0条评论

binaryTree

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<