带有 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;
}
};
我在我的网页中使用 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;
}
};