无法从 ExpressJS res.locals.connection.query() 语句中设置变量 [英] Unable to Set Variable from within ExpressJS res.locals.connection.query() statement

查看:43
本文介绍了无法从 ExpressJS res.locals.connection.query() 语句中设置变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建单点登录功能,以检查是否已配置用户,并创建用户或使用最新信息更新数据库.

I am attempting to create a Single Sign-On feature that checks if a user is already provisioned, and either Creates a user or updates the database with the latest information.

我的更新/插入工作正常,但现在我无法从查询中返回用户 ID(uid 或 UserID).

I have gotten the update/insert working, but now I am unable to return the users id (uid or UserID), from the query.

我已经在该部分评论了我尝试过的一些内容.

I have left several of the things I have tried commented in the section.

基本上,执行插入/更新的查询嵌套在另一个内部,即 post_assert 内部.我需要为刚刚配置的用户提供 iresults.insertId 的值,并将第一级查询的 results[0].nid 的结果保存到 'cookieData' 数组中.

Basically, the query that does the insert/update is nested inside of another, which is inside of the post_assert. I need the value of iresults.insertId for users that were just provisioned and the result of results[0].nid from the first level query to be saved into the 'cookieData' array.

现在,我正在获取 cookie 的其余部分(名字、姓氏、用户名、电子邮件、wwwid、国家/地区和地理位置,但我一生都无法将 cookieData.userid 属性添加到它之前被发送回浏览器.

Right now, I'm getting the rest of the cookie (firstName, lastName, username, email, wwwid, country and geo, but for the life of me cannot get the cookieData.userid property to be added to it before it gets sent back to the browser.

这是一个 expressJS REST API,可将数据发送回 VueJS 应用程序.

This is an expressJS REST API that sends data back to a VueJS Application.

我尝试过回调以及全局变量,但似乎没有任何东西可以将新值添加到数组中.

I have tried callbacks as well as global variables, but nothing seems to add the new value to the Array.

sp.post_assert(idp, options, function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        var sessionID = saml_response.response_header.id;
        setCookie(res, req, sessionID);
        var refererLocation = req.cookies.referLocation;
        // Set User Data Variables
        const firstName = saml_response.user.attributes.givenName;
        const middleName = null;
        const lastName = saml_response.user.attributes.sn;
        const username = saml_response.user.attributes.uid;
        const email = saml_response.user.attributes.mail;
        const wwid = saml_response.user.attributes.employeeID;
        const country = saml_response.user.attributes.country;
        const geo = saml_response.user.attributes.geographicRegion;
        /*function setCookieData(val) {
          cookieData.userid = val;
        }*/
        // let userid;
        // Check if user exists in DB
        res.locals.connection.query('SELECT * FROM users WHERE username = ?', [username], function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // let userid;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            res.locals.connection.query('INSERT INTO users SET ?', {first_name: firstName, middle_name: middleName, last_name: lastName, username: username, email: email, status: 1, created: dts, access: dts, login: dts}, function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // Set the User Data Cookie
              // res.locals.userid = iresults.insertId;
              // setUserIdValue(iresults[0].insertId);
              // res.clearCookie('UserInfo');
              // res.cookie('UserInfo', cookieData);
              // cookieData.userid=iresults[0].insertId;
              // res.cookie('UserInfo', cookieData);
              app.locals.userid = iresults[0].insertId;
            });
          // Else, the result was NOT empty, then the user already exists in the DB,
          // so just update their Access and Login DATETIME fields.
          } else {
            res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // userid = results[0].uid;
              // Set the User Data Cookie
              // res.locals.userid = results[0].uid;
              // setUserIdValue(results[0].uid);
              // res.clearCookie('UserInfo');
              // res.cookie('UserInfo', cookieData);
              // cookieData.userid=results[0].uid;
              // res.cookie('UserInfo', cookieData);
              app.locals.userid = results[0].uid;
            });
          }
        });
        const cookieData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          userid: app.locals.userid,
        };
        res.cookie('UserInfo', cookieData);
        //Add saml ID to database with expiration date
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
        // Save name_id and session_index for logout
        // Note:  In practice these should be saved in the user session, not globally.
        // name_id = saml_response.user.givenName + "," + saml_response.sn;
        // session_index = saml_response.user.session_index;
        //var first = saml_response.user.attributes.givenName;
        //var last = saml_response.user.attributes.sn;
        //res.send("Hello, " + first + " " + last);
    });

我已将其分解为最简单的概念,但仍然无法将userid"值返回到 cookie 中.即使将所有内容都设置为 ASYNC 和 AWAIT.

I have broken it down to it's most simplest concept, and am still unable to get it to return the 'userid' value into the cookie. Even after setting everything to ASYNC and AWAIT.

app.post('/api/v1/saml/acs', function (req, res) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, async function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        const sessionID = saml_response.response_header.id;
        const user = saml_response.user.attributes;
        // Set User Data Variables
        const firstName = user.givenName;
        const middleName = null;
        const lastName = user.sn;
        const username = user.uid;
        const email = user.mail;
        const wwid = user.employeeID;
        const country = user.country;
        const geo = user.geographicRegion;
        app.locals.UserData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          // userid: '',
        };
        // Check if user exists in DB
        await res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], async function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            await res.locals.connection.query('INSERT INTO users SET ?', {first_name: app.locals.UserData.firstName, middle_name: app.locals.UserData.middleName, last_name: app.locals.UserData.lastName, username: app.locals.UserData.username, email: app.locals.UserData.email, status: 1, created: dts, access: dts, login: dts}, async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 22;
              // app.locals.UserData.userid = iresults.insertID;
            });
          } else {
            await res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 44;
              // app.locals.UserData.userid = results[0].uid;
            });
          }
        });
        // Set User Session Cookie
        res.cookie('UserData', app.locals.UserData);
        // Set SAML Session Cookie
        setCookie(res, req, sessionID);
        // Get the referrer location
        var refererLocation = req.cookies.referLocation;
        // If it is undefined, then send the user back to where they started the Sign On process.
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
    });
});

我相信我已经听从了你的建议,但它仍然没有返回 'userid' 属性.

I believe I have followed your advice, but it is still not returning the 'userid' property.

我已将next"参数添加到

I have added the 'next' parameter to

app.post('/api/va/saml/acs', function (){...});

并在末尾添加了next()"调用

and added a 'next()' call at the end of

sp.post_assert(idp, options, async function(...){
    // logic here with nested calls trying to update app.locals.UserData
    next();
});

我也尝试过 post_assert 之外的next()"调用,我收到了这条消息:

I have also tried the 'next()' call outside of the post_assert, and I get this message:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

请参阅下面的更新代码.

See below for the updated code.

app.post('/api/v1/saml/acs', function (req, res, next) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, async function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        const sessionID = saml_response.response_header.id;
        const user = saml_response.user.attributes;
        // Set User Data Variables
        const firstName = user.givenName;
        const middleName = null;
        const lastName = user.sn;
        const username = user.uid;
        const email = user.mail;
        const wwid = user.employeeID;
        const country = user.country;
        const geo = user.geographicRegion;
        app.locals.UserData = {
          firstName: firstName,
          lastName: lastName,
          username: username,
          email: email,
          wwid: wwid,
          country: country,
          geo: geo,
          // userid: '',
        };
        // Check if user exists in DB
        await res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], async function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for insertion
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            await res.locals.connection.query('INSERT INTO users SET ?', {first_name: app.locals.UserData.firstName, middle_name: app.locals.UserData.middleName, last_name: app.locals.UserData.lastName, username: app.locals.UserData.username, email: app.locals.UserData.email, status: 1, created: dts, access: dts, login: dts}, async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 22;
              // app.locals.UserData.userid = iresults.insertID;
            });
          } else {
            await res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], async function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              app.locals.UserData.userid = 44;
              // app.locals.UserData.userid = results[0].uid;
            });
          }
        });
        // Set User Session Cookie
        res.cookie('UserData', app.locals.UserData);
        // Set SAML Session Cookie
        setCookie(res, req, sessionID);
        // Get the referrer location
        var refererLocation = req.cookies.referLocation;
        // If it is undefined, then send the user back to where they started the Sign On process.
        if (refererLocation != undefined) {
            res.clearCookie("referLocation");
            res.redirect('https://www.example.com' + refererLocation);
        } else {
            res.redirect('https://www.example.com/uri');
        }
        next();
    });
});

谢谢 DMFAY 和 BennetQuigley.此问题已解决.

Thank you DMFAY and BennetQuigley. This issue has been resolved.

工作解决方案在下面评论.

The working solution is commented below.

app.post('/api/v1/saml/acs', function (req, res, next) {
    const options = {
        request_body: req.body,
        allow_unencrypted_assertion: true
    };
    sp.post_assert(idp, options, function (err, saml_response) {
        if (err)
            res.redirect('https://www.example.com/');
        // Get the Sessions ID
        const sessionID = saml_response.response_header.id;
        // Set the returned User Info to a Variable
        const user = saml_response.user.attributes;
        // Set the app.locals.UserData variable
        app.locals.UserData = {
          firstName: user.givenName,
          middleName: null,
          lastName: user.sn,
          username: user.uid,
          email: user.mail,
          wwid: user.employeeID,
          country: user.country,
          geo: user.geographicRegion,
        };
        // Check if user exists in DB
        res.locals.connection.query('SELECT * FROM users WHERE username = ?', [app.locals.UserData.username], function (error, results, fields) {
          if (error) throw error;
          // Get the Current Date-Time for Insert/Update of user logon history
          const accessDateTime = new Date();
          const adtYear = accessDateTime.getFullYear();
          const adtMonth = accessDateTime.getMonth() + 1;
          const adtDay = accessDateTime.getDate();
          const adtHour = accessDateTime.getHours();
          const adtMin = accessDateTime.getMinutes();
          const adtSec = accessDateTime.getSeconds();
          const dts = `${adtYear}-${adtMonth}-${adtDay} ${adtHour}:${adtMin}:${adtSec}`;
          // If results is empty, then the user who just logged in does not currently have
          // an account provisioned, so set them up an account.
          if (!(results.hasOwnProperty(0))) {
            res.locals.connection.query('INSERT INTO users SET ?', {
              first_name: app.locals.UserData.firstName,
              middle_name: app.locals.UserData.middleName,
              last_name: app.locals.UserData.lastName,
              username: app.locals.UserData.username,
              email: app.locals.UserData.email,
              status: 1,
              created: dts,
              access: dts,
              login: dts
            }, function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // set the app.locals.UserData.userid value to the newly inserted ID
              app.locals.UserData.userid = `["${iresults.insertID}"]`;
              // From here to 'next()' has to be repeated in both cases
              // 'next()' must be used to return the values and actions to the parent
              // Call.
              // Set User Session Cookie
              res.cookie('UserData', app.locals.UserData);
              // Set SAML Session Cookie
              setCookie(res, req, sessionID);
              // Get the referrer location
              var refererLocation = req.cookies.referLocation;
              // If it is undefined, then send the user back to where they started the Sign On process.
              if (refererLocation != undefined) {
                  res.clearCookie("referLocation");
                  res.redirect('https://clpstaging.mcafee.com' + refererLocation);
              } else {
                  res.redirect('https://clpstaging.mcafee.com/clp');
              }
              // Tell the callback to move forward with the actions.
              next();
            });
          } else {
            res.locals.connection.query('UPDATE users SET login = ?, access = ? WHERE uid = ?', [dts, dts, results[0].uid], function (ierror, iresults, ifields){
              if (ierror) throw ierror;
              // Set the app.locals.UserData.userid to the Users PK
              app.locals.UserData.userid = results[0].uid;
              // From here to 'next()' has to be repeated in both cases
              // 'next()' must be used to return the values and actions to the parent
              // Call.
              // Set User Session Cookie
              res.cookie('UserData', app.locals.UserData);
              // Set SAML Session Cookie
              setCookie(res, req, sessionID);
              // Get the referrer location
              var refererLocation = req.cookies.referLocation;
              // If it is undefined, then send the user back to where they started the Sign On process.
              if (refererLocation != undefined) {
                  res.clearCookie("referLocation");
                  res.redirect('https://www.example.com' + refererLocation);
              } else {
                  res.redirect('https://www.example.com/uri');
              }
              // Tell the callback to move forward with the actions.
              next();
            });
          }
        });
    });
});

推荐答案

您的 post_assert 回调是异步的,但您的路由回调不是,因此路由逻辑在 post_assert 回调完成之前完成.使用 Express 可能最简单的方法是使用 app.post(url, function (req, res, next) {...}) 签名并调用 next()完成写入 cookie 并设置重定向后,作为 post_assert 回调的最后一步.

Your post_assert callback is async but your route callback is not, so the route logic completes before the post_assert callback can finish. Probably your easiest recourse with Express is to use the app.post(url, function (req, res, next) {...}) signature and invoke next() as the last step in the post_assert callback once you've finished writing the cookie and setting up the redirect.

这篇关于无法从 ExpressJS res.locals.connection.query() 语句中设置变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆