使用NTLM的具有Windows身份验证的nginx反向代理

使用NTLM的具有Windows身份验证的nginx反向代理,nginx,reverse-proxy,ntlm,Nginx,Reverse Proxy,Ntlm,有人知道是否可以通过使用NTLM的Windows身份验证执行反向代理吗?我找不到这方面的任何例子。“更多设置标题”字段的值应该是什么 location / { proxy_http_version 1.1; proxy_pass_request_headers on; proxy_set_header Host $host; proxy_set_heade

有人知道是否可以通过使用NTLM的Windows身份验证执行反向代理吗?我找不到这方面的任何例子。“更多设置标题”字段的值应该是什么

location / {
            proxy_http_version      1.1;
            proxy_pass_request_headers on;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;


            more_set_input_headers  'Authorization: $http_authorization';

            proxy_set_header  Accept-Encoding  "";

            proxy_pass              http://host/;
            proxy_redirect          default;
            #This is what worked for me, but you need the headers-more mod
            more_set_headers        -s 401 'WWW-Authenticate: Basic realm="host.local"';
}

如果我直接访问主机,则身份验证成功如果我使用反向代理进行访问,则每次身份验证都会失败

据我所知,nginx目前无法实现这一点。不久前,我自己也对此进行了深入调查。基本问题是NTLM身份验证将要求在后续请求中使用相同的套接字,但代理不会这样做。在nginx开发团队为这种行为提供某种支持之前,我处理这种行为的方式是在反向代理中进行身份验证。我目前正在使用Apache2.2、mod_proxy、mod_auth_sspi(不是完美的,但可以工作)来完成这项工作。祝你好运抱歉,nginx,我爱你,但是我们确实需要一些帮助来解决这个常见的用例。

我已经想出了另一个解决方案。这仍然与nginx执行NTLM不同(如果nginx团队能够实现这一点,这将是一件好事)。但是,现在,我所做的对我们有用

我已经编写了一些使用加密cookie的lua代码。加密的cookie包含用户的id、他进行身份验证的时间和他进行身份验证的ip地址。我把这些东西附在这里作为参考。它没有经过修饰,但也许你可以用它来开发你自己的类似方案

基本上,它的工作原理是:

  • 如果cookie不可用或已过期或无效,nginx将向后端IIS应用程序发出服务调用(预验证),传递客户端的IP地址,然后将客户端重定向到已启用“Windows身份验证”的IIS web应用程序。后端IIS应用程序的预验证服务生成一个GUID,并在数据库中存储该GUID的条目和一个指示此GUID即将进行身份验证的标志
  • nginx会将浏览器重定向到传递GUID的authenticator应用程序
  • IIS应用程序通过windows身份验证对用户进行身份验证,并使用用户id和经过身份验证的时间更新该GUID和客户端IP地址的db记录
  • IIS应用程序将客户端重定向回原始请求
  • nginx lua代码截获此调用,并再次向IIS应用程序发出后门服务调用(post auth),并请求用户id和时间验证。此信息在加密cookie中设置并发送到浏览器。请求被允许通过,远程用户被发送出去
  • 浏览器的后续请求会传递cookie,nginx lua代码会看到有效的cookie,并通过传递远程用户请求头直接代理请求(当然无需再次验证)
  • access.lua:

    local enc     = require("enc");
    local strings = require("strings");
    local dkjson  = require("dkjson");
    
    
    function beginAuth()
        local headers = ngx.req.get_headers();
        local contentTypeOriginal = headers["Content-Type"];
        print( contentTypeOriginal ); 
        ngx.req.set_header( "Content-Type", "application/json" );
        local method = ngx.req.get_method();
        local body = "";
        if method == "POST" then
            local requestedWith = headers["X-Requested-With"];
            if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
                print( "bailing, won't allow post during re-authentication." );
                ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication.  user must do a get first.  cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
                ngx.say("Reload the page.");
                return;
            else
                print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
            end
            ngx.req.read_body();
            local bodyData = ngx.req.get_body_data();
            if bodyData ~= nil then
                body = bodyData;
            end
        end
        local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
        local origData = enc.base64encode( json );
        local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            ngx.header["Access-Control-Allow-Origin"] = "*";
            ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
            ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
        else
            ngx.exit(res.status);
        end
    end
    
    function completeAuth( cookie )
        local guid = enc.decrypt( string.sub( cookie, 6 ) );
        local contentTypeOriginal = ngx.header["Content-Type"];
        ngx.req.set_header( "Content-Type", "application/json" );
        local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            local resJson = res.body;
            -- print( "here a1" );
            -- print( resJson );
            local resTbl = dkjson.decode( resJson );
            if resTbl.StatusCode == 0 then
                resTbl = resTbl.Result;
                local time = os.time();
                local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
                ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
                ngx.req.set_header( "REMOTE_USER", resTbl.user );
                if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
                    local tblJson = enc.base64decode( resTbl.originalData );
                    local tbl = dkjson.decode( tblJson );
                    if tbl.m ~= nil and tbl.m == "POST" then
                        ngx.req.set_method( ngx.HTTP_POST );
                        ngx.req.set_header( "Content-Type", tbl.c );
                        ngx.req.read_body();
                        ngx.req.set_body_data( tbl.d );
                    end
                end
            else
                ngx.log( ngx.ERR, "error parsing json " .. resJson );
                ngx.exit(500);
            end
        else
            print( "error completing auth." );
            ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
            print( res.status );
            ngx.exit(res.status);
        end
    end
    
    
    local cookie = ngx.var.cookie_pca;
    print( cookie );
    if cookie == nil then 
        beginAuth();
    elseif strings.starts( cookie, "guid:" ) then
        completeAuth( cookie );
    else
        -- GOOD TO GO...
        local json = enc.decrypt( cookie );
        local d = dkjson.decode( json );
        local now = os.time();
        local diff = now - d.t;
        local diffOriginal = 0;
        if d.o ~= nil then 
            diffOriginal = now - d.o;
        end
        if diff > 3600 or diffOriginal > 43200 then
            beginAuth();
        elseif diff > 300 then
            print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
            local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
            ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
        end
        ngx.req.set_header( "REMOTE_USER", d.u );
    end
    
    local private = {};
    local public = {};
    strings = public;
    
    function public.starts(String,Start)
       return string.sub(String,1,string.len(Start))==Start
    end
    
    function public.ends(String,End)
       return End=='' or string.sub(String,-string.len(End))==End
    end
    
    return strings;
    
    -- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
    local private = {};
    local public = {};
    enc = public;
    
    local aeslua = require("aeslua");
    
    private.key = "f8d7shfkdjfhhggf";
    
    function public.encrypt( s )
        return base64.base64encode( aeslua.encrypt( private.key, s ) );
    end
    
    function public.decrypt( s )
        return aeslua.decrypt( private.key, base64.base64decode( s ) );
    end
    
    return enc;
    
    upstream dev {
        ip_hash;
        server app.server.local:8080;
    }
    set $authurl http://auth.server.local:8082/root/;
    set $FrontEndProtocol https://;
    location / {
        proxy_pass     http://dev/;
        proxy_set_header Host $host;
        proxy_redirect default;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffers 128 8k;
        access_by_lua_file conf/lua/app/dev/access.lua;
    }
    
    字符串。lua:

    local enc     = require("enc");
    local strings = require("strings");
    local dkjson  = require("dkjson");
    
    
    function beginAuth()
        local headers = ngx.req.get_headers();
        local contentTypeOriginal = headers["Content-Type"];
        print( contentTypeOriginal ); 
        ngx.req.set_header( "Content-Type", "application/json" );
        local method = ngx.req.get_method();
        local body = "";
        if method == "POST" then
            local requestedWith = headers["X-Requested-With"];
            if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
                print( "bailing, won't allow post during re-authentication." );
                ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication.  user must do a get first.  cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
                ngx.say("Reload the page.");
                return;
            else
                print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
            end
            ngx.req.read_body();
            local bodyData = ngx.req.get_body_data();
            if bodyData ~= nil then
                body = bodyData;
            end
        end
        local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
        local origData = enc.base64encode( json );
        local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            ngx.header["Access-Control-Allow-Origin"] = "*";
            ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
            ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
        else
            ngx.exit(res.status);
        end
    end
    
    function completeAuth( cookie )
        local guid = enc.decrypt( string.sub( cookie, 6 ) );
        local contentTypeOriginal = ngx.header["Content-Type"];
        ngx.req.set_header( "Content-Type", "application/json" );
        local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            local resJson = res.body;
            -- print( "here a1" );
            -- print( resJson );
            local resTbl = dkjson.decode( resJson );
            if resTbl.StatusCode == 0 then
                resTbl = resTbl.Result;
                local time = os.time();
                local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
                ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
                ngx.req.set_header( "REMOTE_USER", resTbl.user );
                if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
                    local tblJson = enc.base64decode( resTbl.originalData );
                    local tbl = dkjson.decode( tblJson );
                    if tbl.m ~= nil and tbl.m == "POST" then
                        ngx.req.set_method( ngx.HTTP_POST );
                        ngx.req.set_header( "Content-Type", tbl.c );
                        ngx.req.read_body();
                        ngx.req.set_body_data( tbl.d );
                    end
                end
            else
                ngx.log( ngx.ERR, "error parsing json " .. resJson );
                ngx.exit(500);
            end
        else
            print( "error completing auth." );
            ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
            print( res.status );
            ngx.exit(res.status);
        end
    end
    
    
    local cookie = ngx.var.cookie_pca;
    print( cookie );
    if cookie == nil then 
        beginAuth();
    elseif strings.starts( cookie, "guid:" ) then
        completeAuth( cookie );
    else
        -- GOOD TO GO...
        local json = enc.decrypt( cookie );
        local d = dkjson.decode( json );
        local now = os.time();
        local diff = now - d.t;
        local diffOriginal = 0;
        if d.o ~= nil then 
            diffOriginal = now - d.o;
        end
        if diff > 3600 or diffOriginal > 43200 then
            beginAuth();
        elseif diff > 300 then
            print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
            local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
            ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
        end
        ngx.req.set_header( "REMOTE_USER", d.u );
    end
    
    local private = {};
    local public = {};
    strings = public;
    
    function public.starts(String,Start)
       return string.sub(String,1,string.len(Start))==Start
    end
    
    function public.ends(String,End)
       return End=='' or string.sub(String,-string.len(End))==End
    end
    
    return strings;
    
    -- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
    local private = {};
    local public = {};
    enc = public;
    
    local aeslua = require("aeslua");
    
    private.key = "f8d7shfkdjfhhggf";
    
    function public.encrypt( s )
        return base64.base64encode( aeslua.encrypt( private.key, s ) );
    end
    
    function public.decrypt( s )
        return aeslua.decrypt( private.key, base64.base64decode( s ) );
    end
    
    return enc;
    
    upstream dev {
        ip_hash;
        server app.server.local:8080;
    }
    set $authurl http://auth.server.local:8082/root/;
    set $FrontEndProtocol https://;
    location / {
        proxy_pass     http://dev/;
        proxy_set_header Host $host;
        proxy_redirect default;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffers 128 8k;
        access_by_lua_file conf/lua/app/dev/access.lua;
    }
    
    enc.lua:

    local enc     = require("enc");
    local strings = require("strings");
    local dkjson  = require("dkjson");
    
    
    function beginAuth()
        local headers = ngx.req.get_headers();
        local contentTypeOriginal = headers["Content-Type"];
        print( contentTypeOriginal ); 
        ngx.req.set_header( "Content-Type", "application/json" );
        local method = ngx.req.get_method();
        local body = "";
        if method == "POST" then
            local requestedWith = headers["X-Requested-With"];
            if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
                print( "bailing, won't allow post during re-authentication." );
                ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication.  user must do a get first.  cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
                ngx.say("Reload the page.");
                return;
            else
                print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
            end
            ngx.req.read_body();
            local bodyData = ngx.req.get_body_data();
            if bodyData ~= nil then
                body = bodyData;
            end
        end
        local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
        local origData = enc.base64encode( json );
        local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            ngx.header["Access-Control-Allow-Origin"] = "*";
            ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
            ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
        else
            ngx.exit(res.status);
        end
    end
    
    function completeAuth( cookie )
        local guid = enc.decrypt( string.sub( cookie, 6 ) );
        local contentTypeOriginal = ngx.header["Content-Type"];
        ngx.req.set_header( "Content-Type", "application/json" );
        local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            local resJson = res.body;
            -- print( "here a1" );
            -- print( resJson );
            local resTbl = dkjson.decode( resJson );
            if resTbl.StatusCode == 0 then
                resTbl = resTbl.Result;
                local time = os.time();
                local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
                ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
                ngx.req.set_header( "REMOTE_USER", resTbl.user );
                if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
                    local tblJson = enc.base64decode( resTbl.originalData );
                    local tbl = dkjson.decode( tblJson );
                    if tbl.m ~= nil and tbl.m == "POST" then
                        ngx.req.set_method( ngx.HTTP_POST );
                        ngx.req.set_header( "Content-Type", tbl.c );
                        ngx.req.read_body();
                        ngx.req.set_body_data( tbl.d );
                    end
                end
            else
                ngx.log( ngx.ERR, "error parsing json " .. resJson );
                ngx.exit(500);
            end
        else
            print( "error completing auth." );
            ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
            print( res.status );
            ngx.exit(res.status);
        end
    end
    
    
    local cookie = ngx.var.cookie_pca;
    print( cookie );
    if cookie == nil then 
        beginAuth();
    elseif strings.starts( cookie, "guid:" ) then
        completeAuth( cookie );
    else
        -- GOOD TO GO...
        local json = enc.decrypt( cookie );
        local d = dkjson.decode( json );
        local now = os.time();
        local diff = now - d.t;
        local diffOriginal = 0;
        if d.o ~= nil then 
            diffOriginal = now - d.o;
        end
        if diff > 3600 or diffOriginal > 43200 then
            beginAuth();
        elseif diff > 300 then
            print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
            local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
            ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
        end
        ngx.req.set_header( "REMOTE_USER", d.u );
    end
    
    local private = {};
    local public = {};
    strings = public;
    
    function public.starts(String,Start)
       return string.sub(String,1,string.len(Start))==Start
    end
    
    function public.ends(String,End)
       return End=='' or string.sub(String,-string.len(End))==End
    end
    
    return strings;
    
    -- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
    local private = {};
    local public = {};
    enc = public;
    
    local aeslua = require("aeslua");
    
    private.key = "f8d7shfkdjfhhggf";
    
    function public.encrypt( s )
        return base64.base64encode( aeslua.encrypt( private.key, s ) );
    end
    
    function public.decrypt( s )
        return aeslua.decrypt( private.key, base64.base64decode( s ) );
    end
    
    return enc;
    
    upstream dev {
        ip_hash;
        server app.server.local:8080;
    }
    set $authurl http://auth.server.local:8082/root/;
    set $FrontEndProtocol https://;
    location / {
        proxy_pass     http://dev/;
        proxy_set_header Host $host;
        proxy_redirect default;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffers 128 8k;
        access_by_lua_file conf/lua/app/dev/access.lua;
    }
    
    示例nginx配置:

    local enc     = require("enc");
    local strings = require("strings");
    local dkjson  = require("dkjson");
    
    
    function beginAuth()
        local headers = ngx.req.get_headers();
        local contentTypeOriginal = headers["Content-Type"];
        print( contentTypeOriginal ); 
        ngx.req.set_header( "Content-Type", "application/json" );
        local method = ngx.req.get_method();
        local body = "";
        if method == "POST" then
            local requestedWith = headers["X-Requested-With"];
            if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
                print( "bailing, won't allow post during re-authentication." );
                ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication.  user must do a get first.  cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
                ngx.say("Reload the page.");
                return;
            else
                print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
            end
            ngx.req.read_body();
            local bodyData = ngx.req.get_body_data();
            if bodyData ~= nil then
                body = bodyData;
            end
        end
        local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
        local origData = enc.base64encode( json );
        local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            ngx.header["Access-Control-Allow-Origin"] = "*";
            ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
            ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
        else
            ngx.exit(res.status);
        end
    end
    
    function completeAuth( cookie )
        local guid = enc.decrypt( string.sub( cookie, 6 ) );
        local contentTypeOriginal = ngx.header["Content-Type"];
        ngx.req.set_header( "Content-Type", "application/json" );
        local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
        if contentTypeOriginal ~= nil then
            ngx.req.set_header( "Content-Type", contentTypeOriginal );
        else
            ngx.req.clear_header( "Content-Type" );
        end
        if res.status == 200 then
            local resJson = res.body;
            -- print( "here a1" );
            -- print( resJson );
            local resTbl = dkjson.decode( resJson );
            if resTbl.StatusCode == 0 then
                resTbl = resTbl.Result;
                local time = os.time();
                local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
                ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
                ngx.req.set_header( "REMOTE_USER", resTbl.user );
                if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
                    local tblJson = enc.base64decode( resTbl.originalData );
                    local tbl = dkjson.decode( tblJson );
                    if tbl.m ~= nil and tbl.m == "POST" then
                        ngx.req.set_method( ngx.HTTP_POST );
                        ngx.req.set_header( "Content-Type", tbl.c );
                        ngx.req.read_body();
                        ngx.req.set_body_data( tbl.d );
                    end
                end
            else
                ngx.log( ngx.ERR, "error parsing json " .. resJson );
                ngx.exit(500);
            end
        else
            print( "error completing auth." );
            ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
            print( res.status );
            ngx.exit(res.status);
        end
    end
    
    
    local cookie = ngx.var.cookie_pca;
    print( cookie );
    if cookie == nil then 
        beginAuth();
    elseif strings.starts( cookie, "guid:" ) then
        completeAuth( cookie );
    else
        -- GOOD TO GO...
        local json = enc.decrypt( cookie );
        local d = dkjson.decode( json );
        local now = os.time();
        local diff = now - d.t;
        local diffOriginal = 0;
        if d.o ~= nil then 
            diffOriginal = now - d.o;
        end
        if diff > 3600 or diffOriginal > 43200 then
            beginAuth();
        elseif diff > 300 then
            print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
            local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
            ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
        end
        ngx.req.set_header( "REMOTE_USER", d.u );
    end
    
    local private = {};
    local public = {};
    strings = public;
    
    function public.starts(String,Start)
       return string.sub(String,1,string.len(Start))==Start
    end
    
    function public.ends(String,End)
       return End=='' or string.sub(String,-string.len(End))==End
    end
    
    return strings;
    
    -- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
    local private = {};
    local public = {};
    enc = public;
    
    local aeslua = require("aeslua");
    
    private.key = "f8d7shfkdjfhhggf";
    
    function public.encrypt( s )
        return base64.base64encode( aeslua.encrypt( private.key, s ) );
    end
    
    function public.decrypt( s )
        return aeslua.decrypt( private.key, base64.base64decode( s ) );
    end
    
    return enc;
    
    upstream dev {
        ip_hash;
        server app.server.local:8080;
    }
    set $authurl http://auth.server.local:8082/root/;
    set $FrontEndProtocol https://;
    location / {
        proxy_pass     http://dev/;
        proxy_set_header Host $host;
        proxy_redirect default;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffers 128 8k;
        access_by_lua_file conf/lua/app/dev/access.lua;
    }
    

    使用Nginx启用NTLM直通-

    upstream http_backend {
        server 2.3.4.5:80;
        keepalive 16;
    }
    server {
        ...
        location / {
           proxy_pass http://http_backend/;
           proxy_http_version 1.1;
           proxy_set_header Connection "";
        ...
        }
     }
    

    --Ramon

    好的,我们为nginx/openresty撰写了文章,根据nginx文档,它解决了ntlm反向代理问题,但存在一些可解决的限制,并且不需要商用nginx版本

    允许使用NTLM身份验证代理请求。一旦客户机发送一个“授权”头字段值以“协商”或“NTLM”开头的请求,上游连接就绑定到客户机连接。进一步的客户端请求将通过相同的上游连接进行代理,保持身份验证上下文

    但是ntlm;选项仅适用于商业订阅(Nginx Plus)

    您可以将此模块用于非生产环境


    该模块不完整,但足以解决我的问题。在.

    Tony上也有一篇关于此模块的博文,因此如果我没有弄错,您可以执行以下操作:用户连接到Apache服务器,然后Apache使用NTLM对用户itlsef进行身份验证。之后,Apache启动与某个服务器的反向代理连接并将其发送回用户?基本上是的。客户端向运行mod_auth_sspi的apache进行身份验证。apache将请求代理到某个服务器,同时将用户id注入到请求头中。例如,这是siteminder的一种操作模式。只需确保防止直接访问后端服务器即可。这是一种方法。更好的方法是可能的。例如,重定向到auth服务器并使用oauth2样式的令牌机制。我很想看看你是如何实现这一点的。你会考虑把一个帖子放在一起,让某人通过它,或者以任何方式帮助我吗?我目前有两台ApacheFrone端web服务器,通过NTML对所有用户进行身份验证,速度非常慢。我知道人们会说我可以调优Apache(诸如此类),但我使用nginx的经验是它速度更快,我更愿意使用它。我有IIS框可供使用,因此如果我可以复制您的设置并使用IIS框进行身份验证,并依靠nginx完成Web服务器工作,那将是非常棒的。BeardeGeek,我现在正在阅读这篇文章。如果我很快有时间的话,我会尝试一步一步地组合起来,甚至把它捆绑起来。@BeardeGeek,我所做的不是验证每个请求,而是只验证对应用程序的访问,因此从那时起,应用程序的会话cookie就被使用了。这真的加快了整个过程。我有一个非常类似的问题,如果你有时间,可以回答,目前有悬赏。@Fizz你的意思是我们不需要nginx的商业版本来支持NTLM?这对我不起作用。为什么?在后端使用tomcat。@EdgarChavolla只有在有会话的情况下,它才能与express ntlm一起工作。否则,用户将以其他用户的身份登录。这似乎是可行的,但事实并非如此。就我而言,这导致了