在Nginx中增加对OAuth协议的支持的教程

2019-10-17 20:14:03刘景俊

    ngx.header["Set-Cookie"] = "SGRedirectBack=deleted; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"
    return ngx.redirect(redirect_back)
end

现在我们只需要通过一些请求头信息告知我们当前的应用谁登录了就行了。您可以重用REMOTE_USER,如果你有需求的话,就可以用这个取代基本的身份验证,而除此之外的任何事情都是公平的游戏。

-- Set some headers for use within the protected endpoint
ngx.req.set_header("X-USER-ACCESS-LEVEL", json.access_level)
ngx.req.set_header("X-USER-EMAIL", json.email)

我现在就可以像任何其它的站点那样在我的应用程序中访问这些http头了,而不是用数百行代码和大量的时间来重新实现身份验证。

Nginx 和 Lua, 放在树结构里面

在这一点上,我们应该有一个可以用来阻挡/拒绝访问的LUA脚本。我们可以将这个脚本放到磁盘上的一个文件中,然后使用access_by_lua_file配置来将它应用在我们的nginx站点中。在SeatGeek中,我们使用Chief来模板化输出配置文件,虽然你可以使用Puppet,Fabric,或者其它任何你喜欢的工具。

下面是你可以用来使所有东西都运行起来的最简单的nginx的网站。你也可能会想要检查下access.lua - 在这里 - 它是上面的lua脚本编译后的文件。

# The app we are proxying to
upstream production-app {
  server localhost:8080;
}

# The internal oauth provider
upstream internal-oauth {
  server localhost:1337;
}

server {
  listen       80;
  server_name  private.example.com;
  root         /apps;
  charset      utf-8;

  # This will run for everything but subrequests
  access_by_lua_file "/etc/nginx/access.lua";

  # Used in a subrequest
  location /_access_token { proxy_pass http://internal-oauth/oauth/access_token; }
  location /_user { proxy_pass http://internal-oauth/user; }

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  Host $http_host;
    proxy_redirect    off;
    proxy_max_temp_file_size 0;

    if (!-f $request_filename) {
      proxy_pass http://production-app;
      break;
    }
  }

}

进一步思考

虽然此设置运行的比较好,但是我想指出一些缺点:

    上面的代码是我们access_by_lua脚本的简化。我们也处理保存POST提交的请求,JS加入到到页面更新会话自动处理的令牌更新等,你可能不需要这些功能,而事实上,我不认为我需要它们,直到我们开始了我们在内部系统进行系统测试。     我们有一些结点,可以通过一定的后台任务基本认证。这些被修改,数据是从一个外部存储中检索,如S3。注意,这并不总是可能的,所以使用的可能不是你想要的答案。     Oauth2只是我选择的标准。在理论上,你可以使用facebook授权来实现类似的结果。你也可以将这种方法限速,或存储在数据库中的不同的访问级别如在你的Lua脚本方便操作和检索使用。如果你真的很无聊,你可以重新实现基本认证在Lua,这只需要你。     有没有测试控制系统等。测试者会害怕当他们意识到这将是一段时间的集成测试。你可以重新运行上面的嘲笑为全球范围内注入变量以及执行脚本,但它不是理想的设置。     你还需要修改应用程序识别你的新的访问标头。内部工具将是最简单的,但你可能需要为供应商软件作出一定的让步。