Javascript SPA和SSO中无状态身份验证的性能(单点登录)
如果我有一个SPA(使用BackboneJS开发的单页应用程序),并且希望其数据有一个无状态RESTful后端API。我喜欢第三方单点登录如何让用户的事情变得如此简单,因此会喜欢它使用它Javascript SPA和SSO中无状态身份验证的性能(单点登录),javascript,node.js,rest,authentication,Javascript,Node.js,Rest,Authentication,如果我有一个SPA(使用BackboneJS开发的单页应用程序),并且希望其数据有一个无状态RESTful后端API。我喜欢第三方单点登录如何让用户的事情变得如此简单,因此会喜欢它使用它 但我知道在这样一个无状态的环境中,身份验证是在每个请求上完成的吗?如果是这样,如果我使用的是第三方SSO,例如GitHub,我是否每次都需要转到GitHub对用户进行身份验证?对于这种情况,最佳做法是什么?我相信这是一个非常常见的用例我允许用户通过Google/GitHub或其他方式登录,然后从一些无状态RES
但我知道在这样一个无状态的环境中,身份验证是在每个请求上完成的吗?如果是这样,如果我使用的是第三方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用户) 实施 以下是我实施的内容:
POST/api/board?name=[a_name]&auth=[my_令牌]
时,我知道是谁在调用,可以检查权限,并可以将新创建的实体board
关联到正确的用户authtok