Jwt 如何在配置Fastly CDN时修复Varnish VCL中未终止的短字符串错误

Jwt 如何在配置Fastly CDN时修复Varnish VCL中未终止的短字符串错误,jwt,varnish,varnish-vcl,fastly,fastly-vcl,Jwt,Varnish,Varnish Vcl,Fastly,Fastly Vcl,我正在尝试使用Varnish VCL在Fastly CDN上设置基于令牌的身份验证,并使用此示例VCL片段在此处生成和验证JWT令牌- sub vcl_recv { #FASTLY recv if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") { return(pass); } // Generate

我正在尝试使用Varnish VCL在Fastly CDN上设置基于令牌的身份验证,并使用此示例VCL片段在此处生成和验证JWT令牌-

sub vcl_recv {
    #FASTLY recv

    if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
        return(pass);
    }

    // Generate synth
    if(req.url ~ "generate") {
        error 901;
    }

    // Validate token
    if(req.url ~ "validate") {
        // Ensure token exists and parse into regex
        if (req.http.X-JWT !~ "^([a-zA-Z0-9\-_]+)?\.([a-zA-Z0-9\-_]+)?\.([a-zA-Z0-9\-_]+)?$") {
            // Forbidden
            error 403 "Forbidden";
        }

        // Extract token header, payload and signature
        set req.http.X-JWT-Header = re.group.1;
        set req.http.X-JWT-Payload = re.group.2;
        set req.http.X-JWT-Signature = digest.base64url_nopad_decode(re.group.3);
        set req.http.X-JWT-Valid-Signature = digest.hmac_sha256("SupSecretStr", 
        req.http.X-JWT-Header "." req.http.X-JWT-Payload);
        // Validate signature
        if(digest.secure_is_equal(req.http.X-JWT-Signature, req.http.X-JWT-Valid-Signature)) {
            // Decode payload
            set req.http.X-JWT-Payload = digest.base64url_nopad_decode(req.http.X-JWT-Payload);
            set req.http.X-JWT-Expires = regsub(req.http.X-JWT-Payload, {"^.*?"exp"\s*?:\s*?([0-9]+).*?$"}, "\1");

            // Validate expiration
            if (time.is_after(now, std.integer2time(std.atoi(req.http.X-JWT-Expires)))) {
               // Unauthorized
               synthetic {"{"sign":""} req.http.X-JWT-Signature {"","header":""} req.http.X-JWT-Header {"","payload":""} req.http.X-JWT-Payload {"","valid": ""} req.http.X-JWT-Valid-Signature {""}"};
               return(deliver);
            }

            // OK
            synthetic {"{"header2":""} req.http.X-JWT-Header {"","payload":""} req.http.X-JWT-Payload {"","sign":""} req.http.X-JWT-Signature {"","valid": ""} req.http.X-JWT-Valid-Signature {""}"};
           return(deliver);
        } else {
            // Forbidden
            synthetic {"{"header3":""} req.http.X-JWT-Header {"","payload":""} req.http.X-JWT-Payload {"","sign":""} req.http.X-JWT-Signature {"","valid": ""} req.http.X-JWT-Valid-Signature {""}"};
             return(deliver);
        }
    }

    return(lookup);
}

sub vcl_error {
    #FASTLY error

    // Generate JWT token
    if (obj.status == 901) {
        set obj.status = 200;
        set obj.response = "OK";
        set obj.http.Content-Type = "application/json";

        set obj.http.X-UUID = randomstr(8, "0123456789abcdef") "-" randomstr(4, "0123456789abcdef") "-4" randomstr(3, "0123456789abcdef") "-" randomstr(1, "89ab") randomstr(3, "0123456789abcdef") "-" randomstr(12, "0123456789abcdef");

        set obj.http.X-JWT-Issued = now.sec;
        set obj.http.X-JWT-Expires = strftime({"%s"}, time.add(now, 3600s));

        set obj.http.X-JWT-Header = digest.base64url_nopad({"{"alg":"HS256","typ":"JWT""}{"}"});
        set obj.http.X-JWT-Payload = digest.base64url_nopad({"{"sub":""} obj.http.X-UUID {"","exp":"} obj.http.X-JWT-Expires {","iat":"} obj.http.X-JWT-Issued {","iss":"Fastly""}{"}"});
        set obj.http.X-JWT-Signature = digest.base64url_nopad(digest.hmac_sha256("SupSecretStr", obj.http.X-JWT-Header "." obj.http.X-JWT-Payload));

        set obj.http.X-JWT = obj.http.X-JWT-Header "." obj.http.X-JWT-Payload "." obj.http.X-JWT-Signature;
        unset obj.http.X-UUID;
        unset obj.http.X-JWT-Issued;
        unset obj.http.X-JWT-Expires;
        unset obj.http.X-JWT-Header;
        unset obj.http.X-JWT-payload;
        unset obj.http.X-JWT-Signature;
        synthetic {"{"payload":""} obj.http.X-JWT-Payload {"","header":""} obj.http.X-JWT-Header {"","sign":""} obj.http.X-JWT-Signatre {"","token": ""} obj.http.X-JWT {""}"};
        return(deliver);
    }

    // Valid token
    if (obj.status == 902) {
        set obj.status = 200;
        set obj.response = "OK";
        set obj.http.Content-Type = "application/json";

        synthetic {"{ "token": ""} req.http.X-JWT {"" }"};
        return(deliver);
    }

}
现在,当我试图编译它时,它返回-

Syntax error: Unterminated _short-string_
at: (input Line 106 Pos 197)
               synthetic {"{"sign":""} req.http.X-JWT-Signature {"","header":""} req.http.X-JWT-Header {"","payload":""} req.http.X-JWT-Payload {"","valid": ""} req.http.X-JWT-Valid-Signature {""}"};
看起来在合成块期间,我没有正确地转义这里的值

我尝试在vcl_recv子例程中添加这个合成块的唯一原因是因为我想测试摘要如何生成JWT令牌并验证它,并且我想在Node.Js的服务器端创建类似的JWT令牌,所以我试图输出令牌的不同中间部分以进行调试

我不太熟悉Varnish的语法和语义,但是我仍然在寻找关于这个schedule子例程的文档,但是到目前为止没有找到任何文档

那么,有谁能帮助解决这个问题,让vcl_recv,vcl_error在json响应中插入不同的中间值呢

我尝试使用一些基于Node.Js的base64 url解码库来解码返回的令牌部分,并且能够解码头和有效负载部分,但无法从Node.Js生成签名部分。那么,有人能提出node.js或任何javascript库中base64url_nopad()的等价物吗


对于hmac_256加密部分,我们尝试使用加密库并创建类似hmac的crypto.createHmac('sha256','SupSecretStr').update().digest('hex');但是js中的所有base64编码url库我想都会返回填充url,这就是为什么这个hmac 256摘要中base64编码的部分与varnish生成的部分不匹配的原因。

我的语法着色工具告诉我的与错误消息几乎相同的事情:你把你的引用搞砸了:-)

最后一个块是打开引号(
{“
),立即关闭引号(
“}
),然后打开简单引号,换行符在关闭引号之前到达


要解决这个问题,只需在json的最后一个引号后面加一个空格:
{”“};

那么,结束我在这里编写的json字典块的正确语法应该是什么呢?如果不清楚,很抱歉,我编辑了答案来解释解决方案