带有 LDAP 的 Node.js。如何授权具有相同权限的多个组中的用户

Nodejs with LDAP. How to authorize user in multiple groups having same privileges

我在我的网页中使用 LDAP 身份验证 link 用户登录到他在 Active Directory 中拥有的正确组。我想在用户发出请求时使用这些组来执行授权并且已经成功,直到我注意到当用户属于多个具有相同资源权限的组时,我 运行 进入 "Error: Can't set headers after they are sent.".

错误是由中间件调用的函数引起的,该函数检查组是否应该有权访问资源。因为当多个组具有相同的权限时会多次调用它,所以它最终会多次调用 next()。

我应该如何更改才能让多个组中的用户能够访问相同的资源?我应该能够以某种方式 return 一个阻止对授权函数的任何进一步调用的值,但是我必须在中间件而不是函数中创建响应。

所有这一切可能是由于我对中间件的工作原理缺乏了解造成的,所以如果我的实现中存在一些逻辑错误,我很乐意得到一些反馈。

这里是负责授权的中间件:

app.use(function(reg, res, next){
        var checkSpesificGroup = false;
        var bearerToken;
        console.log(reg.body);
        var bearerHeader = reg.headers.authorization;
        var forbidden=true
        for(käyttäjänOikeus in käyttäjänOikeudet){
                if(käyttäjänOikeudet[käyttäjänOikeus].indexOf(reg.url) > -1){
                        forbidden = false;
                        checkYourPrivilege(käyttäjänOikeus, bearerHeader, res, reg, next);
                }
        }


        if(public.indexOf(reg.url) > -1){
                console.log('public')
                forbidden = false;
                bearerToken = decodeToken(bearerHeader);
                if(bearerToken !== false){
                        decoded = verifyToken(bearerToken);
                        if(decoded !== false){
                                if (checkIfExpired(decoded.expires)){
                                        console.log('checkifexpired success');
                                        res.setHeader('Tokenexpired',false);
                                        next();
                                }else{
                                        console.log('checkifexpired failed');
                                        res.setHeader('Tokenexpired',true);
                                        next();
                                }
                        }else{
                                console.log('decoding failed');
                                res.setHeader('Tokenexpired',false);
                                next();
                        }
                }else{
                        console.log('no bearer token');
                        res.setHeader('Tokenexpired',false);
                        next();
                }
        }
        if(forbidden){
                console.log('forbidden')
                return res.status(403).send({
                        success: false,
                        message: "Forbidden"
                });
        }
});

这是中间件调用的函数,用于对非 public:

的资源执行授权
function checkYourPrivilege(checkSpesificGroup, bearerHeader, res, reg, next){
        bearerToken = decodeToken(bearerHeader);
        if (bearerToken !== false) {
                decoded = verifyToken(bearerToken)
                if (decoded !== false){
                        if (checkIfExpired(decoded.expires)){
                                if(checkSpesificGroup){
                                        if(decoded.oikeudet[checkSpesificGroup] == true){
                                                console.log("Tokenisi vanhentuu" + Math.abs(decoded.expires - Math.floor(Date.now())/100$
                                                reg.decoded = decoded;
                                                res.setHeader('Tokenexpired',false);
                                                next()
                                        }else{
                                                return;
                                        }
                                }else{
                                        console.log("Tokenisi vanhentuu" + Math.abs(decoded.expires - Math.floor(Date.now())/1000) + "pä$
                                        reg.decoded = decoded;
                                        res.setHeader('Tokenexpired',false);
                                        next();
                                }
                        }else{
                                console.log("Token Expired");
                                return res.status(403).send({
                                          success: false,
                                          tokenstatus: "expired",
                                          message: "Token expired"
                                });
                        }
                }else{
                        return res.status(403).send({ success:false, message: 'Invalid token'});
                }
        } else {
                console.log('ei tokenia');
                return res.status(403).send({
                        success: false,
                        message: 'No token provided.'
                });
        }
};

这是包含组信息的数组和包含 public 资源的列表:

var käyttäjänOikeudet =({
"JasentietoSecurity":[],
"JasenSurvivalkit": ['/haut.html','/haku'],
"JasenKV": ['/haut.html','/haku'],
"JasenJasenpalvelu": ['/haut.html','/haku'],
"JasenAsukastoimisto": ['/haut.html','/haku'],
"JasenMaksutiedot":['/varaushaku'],
"JasenSystem": ['/haut.html','/haku','/pk.html','/update','/loki.html', '/raportointi.html','/maksuhaku','/tulosraportti.html']
});

var public = ['/','/login.html','/core.js','/authenticate','/koti.html', '/styles.css','/favicon.ico']

我通过将授权函数从 for 循环中取出并在循环完成后仅调用一次来设法使它工作。

我还需要 return 来自授权函数的值,而不是在内部调用 next()。

这是我对中间件所做的更改:

    var tarkistuslista = []; //Created a list to contain the groups the user is in
    for(käyttäjänOikeus in käyttäjänOikeudet){
            if(käyttäjänOikeudet[käyttäjänOikeus].indexOf(reg.url) > -1){
                    tarkistuslista.push(käyttäjänOikeus); //Instead of calling the authorization function, this part pushes the group in the list instead
            }
    }
    //Added the following if statement
    if (tarkistuslista.length > 0){
            privilege = checkYourPrivilege(tarkistuslista, bearerHeader)
            if(privilege == true){
                    next();
            }else{
                    return res.status(403).send(privilege);
            }
    }

我还需要对授权功能做一些修改:

function checkYourPrivilege(tarkistuslista, bearerHeader){
        bearerToken = decodeToken(bearerHeader);
        if (bearerToken !== false) {
                decoded = verifyToken(bearerToken)
                if (decoded !== false){
                        if (checkIfExpired(decoded.expires)){
                                n = 1;
                                privilege = false;
                                for(i in tarkistuslista){
                                        if(decoded.ryhmäoikeudet[tarkistuslista[i]]){
                                                privilege = true
                                                console.log("Tokenisi vanhentuu" + Math.abs(decoded.expires - Mat$
                                                return true;
                                                break;
                                        }else{
                                                if(n == tarkistuslista.length && privilege == false){
                                                        response = ({
                                                          success: false,
                                                          message: "Forbidden"
                                                        });
                                                        return response;
                                                }
                                                n +=1;
                                        }
                                };
                        }else{
                                console.log("Token Expired");
                                response = ({
                                          success: false,
                                          tokenstatus: "expired",
                                          message: "Token expired"
                                });
                                return response;
                        }
                }else{
                        response = ({ success:false, message: 'Invalid token'});
                        return response;
                }
        } else {
                response = ({
                        success: false,
                        message: 'No token provided.'
                });
                return response;
        }
};