繁体   English   中英

如何将带有 json 主体的子请求从 NGINX http 请求 ZA8CFDE6331BD59EB2ACZ66F89 发布到另一台服务器

[英]How to post a subrequest with a json body to another server from NGINX http request object

与 Auth0 的接口需要带有 json 主体的发布请求以检索令牌并将其设置在 Header 授权承载中。 我无法在令牌的 nginx js mdoule 的子请求中设置 json 主体。 请指教

```
function introspectAccessToken(r) {
    // Prepare Authorization header for the introspection request
    var jsbody = {"grant_type" : "authorization_code",
              "client_id" : r.variables.oauth_client_id,
              "client_secret" : r.variables.oauth_client_secret,
              "code" : r.args_code,
              "redirect_uri":"http://office.etag-hk.com/login"};
    var jsString = JSON.stringify(jsbody);
    r.RequestBuffer = jsString;
    // Make the OAuth 2.0 Token Introspection request
    r.error("OAuth jsbody: " + jsString);
    r.subrequest("/_oauth2_send_introspection_request",
        function(reply) {
           if (reply.status != 200) {
               r.error("OAuth unexpected response from authorization server (HTTP " + reply.status + 
            "). " + reply.body);
                r.return(401);
            }
Thanks

我正在做一些非常相似的事情,只是让它“大部分”按照我昨天想要的方式工作。

披露:我是 NGINX 的 NUBE。 我正在发布我所做的事情,希望能对您有所帮助,并获得有关如何改进的任何反馈。

我的用例:我有许多客户端从后端服务器请求数据。 我需要缓存响应以减少后端的负载,并为客户端对后端服务器进行身份验证。 NGINX 服务器将管理 ID/PWD 和 Token,客户端只会发出请求。 在第一个请求或令牌过期时,NGINX 需要获取新的令牌。 身份验证通过 POST 请求完成,在 JSON 主体中传递 ID 和密码。

我希望客户端永远不会看到 401。我正在使用 NGINX JavaScript 模块。

我现在关闭了缓存以确保身份验证正常工作。

Javascript:

function introspectAccessToken(r)
{
    r.log("introspectAccessToken - make a subrequest to _oauth2_send_request");

    // Request Internal location "SEND REQUEST"
    r.subrequest("/_oauth2_send_request",
    { method: 'POST',
      body: JSON.stringify({ userName: "SERVICEID", password: "correcthorsebatterystaple" })
    },
    function(reply)
    {
       …

我的身体是 static,目前,我的 ID 和密码在代码中以明文形式显示,这并不理想。 我喜欢你如何在一个变量中建立你的身体。 我认为您需要将 jsString 放入您的子请求调用中,而不是设置 r.RequestBuffer。

在 my.Conf 文件中:

location /_oauth2_send_request {
    internal;
    proxy_method      POST;
    proxy_set_header accept "application/json";
    proxy_set_header Content-Type "application/json";
    proxy_pass https://backend.company.com/login;
}

令牌在正文中返回。 我解析正文并获取令牌数据。 最初我试图通过以下方式获取令牌:

js_set    $token   myJavaScript.getToken;

在配置中,但 r.subrequest 是异步调用,并且在变量处理程序中是不允许的。
所以,我“踢”并将令牌数据写入文件。 这对我来说可能是一个大错误,但它帮助我让它发挥作用。

这是我的更多 javascript:

function(reply)
{
    if (reply.status == 200)
    {
        r.log("introspectAccessToken: POST status:" + reply.status);
        var response = JSON.parse(reply.responseBody);
        var token = response["data"];
        // Write the Token to a file -- to be read later.
        writeToken(token);
        return(200);
    else
    {
        r.log("introspectAccessToken: failed POST status:" + reply.status);
        r.return(401);
    }
});

现在令牌在文件中,我可以使用变量处理程序来读取文件(同步)并返回令牌数据。 配置文件。

js_set $myToken myJavaScript.readToken;

我挣扎了一段时间的地方是将最初的 401 授权重定向回 NGINX 而不是客户端。 指令error_page 401,在许多不同的格式中,似乎根本不起作用,我什至在博客和帖子中读到它不起作用,但在其他示例中声称它确实起作用。 我认为关键是这一行:proxy_intercept_errors on;

添加后,最初的401未授权错误被重定向:error_page 401 = @Unauthorized;

我现在拥有的如下: 1:客户端发出初始 GET 请求以获取一些数据。 readToken function 返回一个空字符串,因为令牌文件不存在。 来自后端的响应是“401 Unauthorized”。 2:401重定向,javascript对ID/PWD登录进行子请求。 3:解析响应并将令牌写入文件。 4:??? 客户端收到 404 Not Found 代码。 这就是我想要改进的。 我想使用新令牌对后端进行另一次尝试。 5:第一次尝试失败,客户端执行重试。 现在在 NGINX 服务器上使用保存的令牌,请求成功。

我的完整 conf 文件:

# Location of JavaScript code
js_import ./javascript/myJavaScript.js;

js_set $myToken myJavaScript.readToken;

server
{
    listen 80;

    access_log /var/log/nginx/access.log main1;

    # This is run for every request.
    location / {
        # Make an Internal Redirect if Not Authorized.
        proxy_intercept_errors on;
        error_page 401 = @Unauthorized;

        proxy_set_header accept "application/json";
        proxy_set_header Content-Type "application/json";
        proxy_set_header Authorization $myToken;
        proxy_pass https://backend.company.com;

    }

    location  @Unauthorized {
        internal;
        auth_request /_oauth2_token_introspection;
    }

    location = /_oauth2_token_introspection {
        internal;
        # Calls the javascript function
        js_content myJavaScript.introspectAccessToken;
    }

    # Location in javascript subrequest.
    location /_oauth2_send_request {
        internal;
        proxy_method      POST;
        proxy_set_header accept "application/json";
        proxy_set_header Content-Type "application/json";
        proxy_pass https://imos-plant-config-api-test.op-epg1mi.gm.com/tonic/login;
    }
}

我的完整 javascript:

var fs = require('fs');
var MyTokeFile = "/etc/nginx/protectedFolder/mytoken.dat";

function writeToken(t)
{
    var file = fs.writeFileSync(MyTokeFile, t)
}

function readToken(r)
{
    try {
        fs.accessSync(MyTokeFile, fs.constants.R_OK);
        r.log('readToken: Has READ access : ' + MyTokeFile);
    } catch (e) {
        r.log('readToken: No READ access : ' + MyTokeFile);
        return ("");  // Return empty string if file cannot be read.
    }

    r.log("readToken:" + MyTokeFile )
    var file = fs.readFileSync(MyTokeFile);
    var token = file.toString();
    return (token);
}

function introspectAccessToken(r)
{
    r.log("introspectAccessToken - make a subrequest to _oauth2_send_request");
    // Request Internal location "SEND REQUEST"
    r.subrequest("/_oauth2_send_request",
    { method: 'POST',
      body: JSON.stringify({ userName: "SERVICEID", password: "correcthorsebatterystaple" })
    },
    function(reply)
    {
        if (reply.status == 200)
        {
            r.log("introspectAccessToken: POST status:" + reply.status);
            var response = JSON.parse(reply.responseBody);
            var token = response["data"];
            // Write the Token to a file -- to be read later.
            writeToken(token);
            r.return(200);
        }
        else
        {
            r.log("introspectAccessToken: failed POST status:" + reply.status);
            r.return(401);     // Unexpected response, return 'auth required'
        }
    });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM