Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript SPA和SSO中无状态身份验证的性能(单点登录)_Javascript_Node.js_Rest_Authentication - Fatal编程技术网

Javascript SPA和SSO中无状态身份验证的性能(单点登录)

Javascript SPA和SSO中无状态身份验证的性能(单点登录),javascript,node.js,rest,authentication,Javascript,Node.js,Rest,Authentication,如果我有一个SPA(使用BackboneJS开发的单页应用程序),并且希望其数据有一个无状态RESTful后端API。我喜欢第三方单点登录如何让用户的事情变得如此简单,因此会喜欢它使用它 但我知道在这样一个无状态的环境中,身份验证是在每个请求上完成的吗?如果是这样,如果我使用的是第三方SSO,例如GitHub,我是否每次都需要转到GitHub对用户进行身份验证?对于这种情况,最佳做法是什么?我相信这是一个非常常见的用例我允许用户通过Google/GitHub或其他方式登录,然后从一些无状态RES

如果我有一个SPA(使用BackboneJS开发的单页应用程序),并且希望其数据有一个无状态RESTful后端API。我喜欢第三方单点登录如何让用户的事情变得如此简单,因此会喜欢它使用它


但我知道在这样一个无状态的环境中,身份验证是在每个请求上完成的吗?如果是这样,如果我使用的是第三方SSO,例如GitHub,我是否每次都需要转到GitHub对用户进行身份验证?对于这种情况,最佳做法是什么?我相信这是一个非常常见的用例我允许用户通过Google/GitHub或其他方式登录,然后从一些无状态REST API获取数据,实现方法是在客户端(主干网)和RESTful Web服务器之间引入代理。代理结合SSO管理用户的身份验证。因此,无需更改api和/或客户端/Web服务器。下面是一个快速演示:

var http = require('http'),
    httpProxy = require('http-proxy'),
    express = require('express');

var proxy = new httpProxy.RoutingProxy();
var app = express();

function ensureAuthenticated(req, res, next) {
  if (isLoggedIn) { return next(); }
  res.redirect('/');
}

// This should be your (RESTful) webserver
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

var isLoggedIn = false;

app.get('/', function(req, res){
  console.log(isLoggedIn)
  res.send('Logged in? ' + isLoggedIn);
});

app.get('/login', function(req, res){
  isLoggedIn = true;
  res.redirect('/');
});

app.get('/logout', function(req, res){
  isLoggedIn = false;
  res.redirect('/');
});

app.all('/api/*', ensureAuthenticated, function(req, res) {
  return proxy.proxyRequest(req, res, {
    host: 'localhost',
    port: 9000
  });
});

app.listen(8000);
第一次访问该页面时,您已注销,对
/api/something
的任何调用都会被重定向到
/
。登录后(访问
/login
页面),对
/api/*
的所有请求都将通过代理路由到侦听端口9000的Web服务器


特别是,当您设置
app.all(“/*”,…)
时,对API服务器的所有调用都保持不变,但都增加了一个身份验证层。用oauth扩展这个概念很简单(看看您是否在使用node)。

您可以采用Facebook的JavaScript SDK中使用的方法

不是很深入,但解释了如何使用他们的方法的基本原理。但是,没有提到签名的可能性

为应用程序注册Facebook登录时,您会从Facebook上的应用程序仪表板获得应用程序机密

当用户通过Facebook登录到你的应用程序时,你的JavaScript将获得一个身份验证对象。此对象包含签名。(如果在仪表板中设置正确。)

您可以通过对RESTful服务器的客户端调用提供此身份验证对象,并在服务器上检查签名是否正确。这样,您就知道该用户已通过facebook的身份验证,即该用户,并且已针对您的应用程序进行身份验证

不要被标题中的“游戏”吓倒,它对任何web应用程序都非常有效

与只允许Facebook进行SSO不同,您可以使用其他OAUTH提供商以与FB登录相同的精神实现某些东西

使用danielepolencic建议的解决方案,但对其进行修改,以使您有另一台服务器进行登录,而不是在同一node.js实例中使用代理。该服务与提供者进行OAUTH检查,并维护与客户端的会话。它向客户机发送一个签名令牌,并且有很短的生存时间。客户端必须在生存时间结束之前请求新令牌

然后实现一个客户端JavaScript,其功能类似于Facebook JavaScript SDK,用于应用程序使用的登录。此函数可以轮询新令牌,也可以根据请求检索新令牌,这对于场景来说是最有效的

客户机在每次请求时向RESTful API提供该令牌,服务器检查签名。就像Facebook的SSO一样

仍然有一个会话,但它可以在完全不同的机器上进行维护。使用RESTful api,此服务可以独立于服务器进行扩展

但是,请记住,这种方法可能容易受到中间人攻击和重播攻击。不使用https可能是不明智的

免责声明:) 在我的产品中实现了这样一个东西,并分享了您的许多关注点和技术(特别是使用100%无状态REST后端的主干SPA),我可以告诉您我对此的想法,明确表示这不是“答案”,而是从讨论中学习的对话开始,我想在这个话题上我也有很多东西要学


首先,我认为你应该100%无国籍。100%,我的意思是100%:)不仅您的API层应该是无状态的,而且整个应用程序(当然,除了客户端)也应该是无状态的。将会话移动到另一层(如redis)只会稍微移动问题,但无法解决问题。一切(尤其是缩放)都会变得容易得多,稍后您会感谢自己的决定

因此,是的,您需要对每个请求进行身份验证。但这并不意味着您每次都必须访问身份验证提供程序。我学到的一点是,允许用户通过FB/GitHub/任何东西(从现在起,远程服务)进行身份验证只是为了减轻注册/登录的痛苦,而不是别的。你仍然需要增加你的个人用户数据库。当然,每个用户都将关联到一个“远程”用户,但在执行身份验证后不久,应用程序应该引用“您的”用户,而不是“远程”用户(例如GitHub用户)

实施 以下是我实施的内容:

  • 我的API方法总是需要身份验证令牌。auth令牌是代表我的系统用户的散列,因此当我调用
    POST/api/board?name=[a_name]&auth=[my_令牌]
    时,我知道是谁在调用,可以检查权限,并可以将新创建的实体
    board
    关联到正确的用户

  • 所述令牌与远程服务的令牌无关。它们的计算逻辑特定于我的应用程序。但它映射了我的一个用户,也映射到了一个远程用户,所以在需要时不会丢失任何信息

  • 下面是我如何通过远程服务对用户进行身份验证。我实现了服务文档中指定的远程身份验证。通常它是OAuth或类似OAuth的,这意味着最终我会得到一个
    authtok