首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于上游状态码触发openidc认证

基于上游状态码触发openidc认证
EN

Stack Overflow用户
提问于 2020-03-12 15:54:25
回答 1查看 350关注 0票数 2

我正在使用lua-resty-openidc实现一个位于后端系统前面的web。

后端提供一个REST,由包含JWT的Authorization头保护。前端管理会话,如果用户需要登录,则将其发送给身份提供者。当web用户有会话时,前端必须查找JWT,将其添加到授权头,并将请求代理到后端--非常标准的内容。

不幸的是,我的后端并没有明确区分公共资源和私人资源。例如,它可能有带有URL的资源:

  • /api/public/0
  • /api/public/1
  • /api/private/2
  • /api/private/3

它允许在没有授权头的情况下请求/api/public/{0,1},但是/api/private/{2,3}需要授权。前面的人必须以某种方式处理这件事。(注意:上面的URL是简化的,真实的URL不遵循模式,很难被枚举。)

核心问题是前端无法从请求URI中判断是否应该触发登录。它必须是反应性的,将请求代理到后端并检查响应代码。401代码应强制客户端登录,但任何其他响应都应按原样返回。

因此,我不能将我的auth逻辑放在access_by_lua块中,因为它们在访问阶段中运行,然后请求被发送到上游(后端)。

我尝试使用一个块将我的逻辑移到内容阶段:

代码语言:javascript
运行
复制
location /api {
  set $session_storage shm;
  proxy_set_header X-Forwarded-Host  $http_host;
  proxy_pass https://backend;

  body_filter_by_lua_block {
    if ngx.status == ngx.HTTP_UNAUTHORIZED then
      ngx.log(ngx.INFO, 'Upstream returned a 401! Triggering auth flow')

      local opts = {
        discovery = 'https://login-server/.well-known/openid-configuration',
        scope = 'openid',
      }

      local res, err = openidc.authenticate(opts)
      if err or not res then
        ngx.status = ngx.HTTP_UNAUTHORIZED
        ngx.header.content_type = 'text/html';
        ngx.log(ngx.ERR, err)
        ngx.say("Forbidden")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
      end

    end
  }
}

…但如果出现错误(如下所示),则会失败。在请求处理生命周期中,设置头和cookie似乎为时已晚:

代码语言:javascript
运行
复制
*194 [lua] body_filter_by_lua:5: Upstream returned a 401! Triggering auth flow while sending to client, client: 10.255.1.2, server: , request: "GET /api/private/2 HTTP/1.1", upstream: "https://backend/api/private/2", host: "frontend.example.org"

*194 [lua] openidc.lua:1363: authenticate(): Error starting session: Attempt to set session cookie after sending out response headers. while sending to client, client: 10.255.1.2, server: , request: "GET /api/private/2 HTTP/1.1", upstream: "https://backend/api/private/2", host: "frontend.example.org"

*194 attempt to set ngx.status after sending out response headers while sending to client, client: 10.255.1.2, server: , request: "GET /api/private/2 HTTP/1.1", upstream: "https://backend/api/private/2", host: "frontend.example.org"

是否可以在Nginx请求处理的openidc.authenticate()内容阶段执行?

有什么更好的方法吗?

EN

回答 1

Stack Overflow用户

发布于 2020-11-30 14:47:57

最后,我调整了后端使用的URL模式,这样可以预先区分私有URL和公共URL。然后,前端逻辑变得简单起来:

对公共资源的backend

  • request

  • 请求:私有资源的
  • 请求,没有授权头:返回针对私有资源的401
  • 请求,而授权头:代理到后端

我不知道我最初的问题(先代理,然后根据响应代码做出决定)在OpenResty中是否可行。但最终,我认为新的方法还是比较干净的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60657661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档