加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angularjs – 更新自定义req.session属性值似乎不够持久

发布时间:2020-12-17 10:23:39 所属栏目:安全 来源:网络整理
导读:我有一些Express中间件处理来自我的客户端应用程序的GET请求,以便后续请求使用OAuth2令牌的单独API服务器,我也使用快速会话来存储这些令牌. 在我发出传出请求的中间件中,我添加了处理以应对访问令牌到期的情况(API服务器发回403)并发出刷新令牌的请求,之后它
我有一些Express中间件处理来自我的客户端应用程序的GET请求,以便后续请求使用OAuth2令牌的单独API服务器,我也使用快速会话来存储这些令牌.

在我发出传出请求的中间件中,我添加了处理以应对访问令牌到期的情况(API服务器发回403)并发出刷新令牌的请求,之后它将发出相同的原始传出请求API服务器,所以客户端不知道这一切都在发生.然后,通过快速会话将检索到的新令牌持久保存回会话存储,以便在后续请求中使用.令牌也用于设置授权承载令牌标头,您将在下面进一步了解.

以下是我的Express代码中涉及的部分:

routes.controller.js

//Currently handling GET API requests from client
module.exports.fetch = function(req,res) {
  var options = helpers.buildAPIRequestOptions(req);
  helpers.performOutgoingRequest(req,res,options);
};

helpers.js

module.exports.buildAPIRequestOptions = function(req,url) {
  var options = {};
  options.method = req.method;
  options.uri = 'http://someurl.com' + req.path;
  options.qs = req.query;
  options.headers = {
    'Authorization': 'Bearer ' + req.session.accessToken
  };
  return options;
};

module.exports.performOutgoingRequest = function(req,options) {
  request(options,function(err,response,body){
    if(response.statusCode === 401){
      console.log(chalk.red('n--- 401 RESPONSE RECEIVED TRY REFRESHING TOKENS ---'));
      //Note the third param to call below is a callback and is invoked when calling next() in the refreshToken middleware
      authController.refreshToken(req,function(){
        console.log(chalk.green('n--- RETRYING ORIGINAL REQUEST WITH UPDATED ACCESS TOKEN ---'));
        //Re-use original request options,but making sure we update the Authorization header beforehand
        options.headers.Authorization = 'Bearer ' + req.session.accessToken;
        retryOutgoingRequest(res,options);
      });
    } else {
      res.status(response.statusCode).send(body);
    }
  }); 
};

function retryOutgoingRequest(res,body){
    if(err) {
      console.log(err);
    }
    res.status(response.statusCode).send(body);
  });
};

auth.controller.js

module.exports.refreshToken = function(req,next) {
  var formData = {
      grant_type: 'refresh_token',refresh_token: req.session.refreshToken
    },headers = {
      'Authorization' : 'Basic ' + consts.CLIENT_KEY_SECRET_BASE64
    };
  request.post({url:consts.ACCESS_TOKEN_REQUEST_URL,form:formData,headers: headers,rejectUnauthorized: false},body){
    var responseBody = JSON.parse(body);
    if (response.statusCode === 200) {
      req.session.accessToken = responseBody.access_token;
      req.session.refreshToken = responseBody.refresh_token;
      next();
    } else {
      console.log(chalk.yellow('A problem occurred refreshing tokens,sending 401 HTTP response back to client...'));
      res.status(401).send();
    }
  });
};

在大多数情况下,上述工作正常

当用户首次登录时,在将API服务器带到应用程序的主页面之前,会从API服务器获取一些其他用户配置文件信息.

应用程序中的某些页面也会在页面加载时获取数据,因此需要进行访问令牌检查.

在正常使用期间,所以当用户登录并开始在页面周围点击时,我可以看到令牌被换出并在会话存储中通过快速会话保存到期时.根据我编写的中间件,新的访问令牌正确地用于后续请求.

我现在有一个我的中间件不起作用的场景.

所以说我在一个页面加载页面加载数据,让我们说它是一个订单页面.如果我等到API服务器上配置的令牌到期时间已经过去然后刷新浏览器,则客户端应用程序将首先请求用户信息,然后成功将请求页面所需的订单数据(使用AngularJS承诺)

在我的Express应用程序中,用户信息请求从API服务器获取403,因此令牌通过上面的中间件刷新,并且req.session.accessToken得到更新,我可以通过我的服务器应用程序中的控制台日志记录看到.但是,下次获取订单的数据最终会使用先前设置的访问令牌,这会导致API服务器发生进一步的未经授权的错误,因为正在使用无效令牌进行请求.

如果我再次刷新浏览器,则使用先前中间件流中的正确更新令牌获取用户信息和订单.

所以我不确定这里发生了什么,我想知道这是否是一个时间问题,req.session对象没有被及时保留回会话存储区以便下一次请求获取?

任何人都有任何想法可能会发生在这里?

谢谢

更新1

根据评论中的要求,这里是两个请求的请求和响应标头.

第一个请求(使用更新的令牌服务器端)

请求标题

GET /api/userinfo HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Accept: application/json,text/plain,*/*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/50.0.2661.94 Safari/537.36
Referer: https://localhost:5000/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Cookie: interact.sid=s%3A0NDG_bn67NeGQAYl1wP1-TmM19ExavFm.Zjv65e9BtSyNBuo%2FDxZEk2Np0963frVur4zHyYw3y5I

响应标题

HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=86400
X-Download-Options: noopen
X-XSS-Protection: 1; mode=block
Content-Type: text/html; charset=utf-8
Content-Length: 364
ETag: W/"16c-4AIbpZmTm3I+Yl+SbZdirw"
set-cookie: interact.sid=s%3A0NDG_bn67NeGQAYl1wP1-TmM19ExavFm.Zjv65e9BtSyNBuo%2FDxZEk2Np0963frVur4zHyYw3y5I; Path=/; Expires=Fri,13 May 2016 11:54:56 GMT; HttpOnly; Secure
Date: Fri,13 May 2016 11:24:56 GMT
Connection: keep-alive

第二个请求(使用旧令牌服务器端)

请求标题

GET /api/customers HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Accept: application/json,en;q=0.6
Cookie: interact.sid=s%3A0NDG_bn67NeGQAYl1wP1-TmM19ExavFm.Zjv65e9BtSyNBuo%2FDxZEk2Np0963frVur4zHyYw3y5I

响应标题

HTTP/1.1 401 Unauthorized
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=86400
X-Download-Options: noopen
X-XSS-Protection: 1; mode=block
set-cookie: interact.sid=s%3A0NDG_bn67NeGQAYl1wP1-TmM19ExavFm.Zjv65e9BtSyNBuo%2FDxZEk2Np0963frVur4zHyYw3y5I; Path=/; Expires=Fri,13 May 2016 11:24:56 GMT
Connection: keep-alive
Content-Length: 0

更新2

我还应该提到我使用connect-mongo作为我的会话存储,我尝试使用默认的内存存储但存在相同的行为.

它听起来像一个竞争条件客户端,如果你正在执行2个请求(检查auth – 然后获取数据)是第二个(获取数据)嵌套到第一次调用成功?或者你是否同时线性地呼叫?

我的想法是:

客户端 – 发送用户信息请求(sessionid 1) – 服务器处理

客户端 – 获取订单信息请求(sessionid 1) – 服务器处理

服务器 – 响应用户信息 – 403 – 客户端更新会话ID

服务器 – 响应订单信息 – 403

你真正想要的是:

客户端 – 发送用户信息请求(会话1) – 服务器处理

server – 获取用户信息请求(403) – 客户端更新会话ID

客户端 – 获取订单信息请求(会话2) – 服务器处理

服务器 – 响应订单信息 – 实际结果

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读