首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SPA和SSO (单点登录)中的无状态身份验证性能

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

Stack Overflow用户
提问于 2013-08-11 11:29:12
回答 3查看 2.9K关注 0票数 6

如果我有一个SPA (单页应用程序-用BackboneJS开发的),并且想要有一个无状态的RESTful后端应用程序接口来处理它的数据。我喜欢第三方单点登录让用户的事情变得如此简单,因此会喜欢使用它。

但我知道,在这样的无状态环境中,身份验证是针对每个请求进行的吗?如果是这样,如果我正在使用第三方SSO,例如。GitHub,我不是每次都需要转到GitHub来验证用户吗?对于这种情况,最佳实践是什么?我相信这是一个非常常见的用例--我允许用户通过Google/GitHub或其他方式登录,然后从某个无状态的REST API获取数据

EN

回答 3

Stack Overflow用户

发布于 2013-08-20 23:18:03

免责声明:)

我已经为我的产品实现了这样一个东西,并分享了您的许多关注点和技术(特别是使用100%无状态REST后端的骨干SPA ),我可以告诉您我对此的想法,清楚地表明这不想成为“答案”,而是从由此产生的讨论中学习,因为我认为我在这个主题上也有相当多的东西需要学习。

首先,我认为你应该100%无国籍。100%,我的意思是100% :)不仅你的API层应该是无状态的,而且整个应用程序(当然除了客户端)都应该是无状态的。在不同的层上移动会话(例如,redis)只是稍微转移了一下问题,但并没有解决它。一切(尤其是伸缩)都会变得容易得多,稍后你会因为这个决定而感谢自己。

因此,是的,您需要对每个请求进行身份验证。但这并不意味着您必须每次都访问身份验证提供商。我学到的一件事是,允许用户通过FB/GitHub/任何方式(从现在开始,远程服务)进行身份验证只是一种缓解注册/登录痛苦的方法,除此之外没有别的。你仍然需要增加你的用户的个人数据库。当然,每个用户都将关联到一个“远程”用户,但在执行身份验证后不久,应用程序应该引用“您的”用户,而不是“远程”用户(例如。GitHub用户)。

实现

下面是我实现的内容:

  1. My API methods always需要身份验证令牌。auth令牌是表示系统用户的散列,因此当我调用POST /api/board?name=[a_name]&auth=[my_token]时,我知道是谁在调用,可以检查权限,并可以将新创建的实体board关联到正确的用户。
  2. 上述令牌与远程服务的令牌无关。它们的计算逻辑特定于我的应用程序。但是它映射了我的一个用户,这个用户也映射到一个远程用户,所以如果我通过远程服务验证用户的方式是needed.
  3. Here's的,那么不会丢失任何信息。我实现了服务文档中指定的远程身份验证。通常它是OAuth或类似于OAuth的,这意味着最终我会得到一个表示远程用户的authToken。此内标识有两个用途:

代码语言:javascript
复制
- I can use it to call API methods on the remote service acting as the user
- I have the guarantee that the user is who it says it is, at least by the means of the remote service

  1. 一旦您的用户通过远程服务的身份验证,您就可以在系统中加载或创建匹配的用户。如果系统中不存在具有remote_id: GitHub_abc123的用户,则创建该用户,否则加载该用户。假设这个用户有id: MyApp_def456。您还可以使用自己的逻辑创建一个表示用户MyApp_def456authToken,并将其传递给客户端(cookies就可以了!!)
  2. 返回到点1 :)

备注

身份验证是在每次请求时执行的,这意味着您要处理散列和加密函数,这样定义的速度会很慢。现在,如果你使用20次迭代的bcrypt,这将杀死你的应用程序。当用户登录时,我使用它来存储用户的密码,但是对authToken使用一种不那么繁重的算法(我个人使用一种类似于SHA-256的散列)。这个令牌可以是短暂的(比方说少于平均破解它们的时间),并且在服务器机器上很容易计算。这里没有一个确切的答案。尝试不同的方法,衡量并决定。相反,我可以肯定的是,我更喜欢有这种问题,而不是会话问题。如果我需要计算更多的散列,或者更快,我会增加CPU能力。对于会话和集群环境,您会遇到内存问题、负载平衡和粘性会话问题,或者其他移动块(Redi)。

显然,HTTPS是绝对强制的,因为authToken总是作为参数传递的。

票数 11
EN

Stack Overflow用户

发布于 2013-08-16 18:43:02

我实现它的方式是在客户端(主干)和RESTful way服务器之间引入一个代理。代理与SSO一起管理用户的身份验证。因此,无需更改api和/或客户端/and服务器。下面是一个快速演示:

代码语言:javascript
复制
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的When服务器。

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

票数 1
EN

Stack Overflow用户

发布于 2013-08-20 01:30:15

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

This documentation page provides the quick-start to login vith Facebook for web.不是很深入,但解释了如何使用他们的方法的基本知识。但是,没有提到签名的可能性。

在为您的应用程序注册Facebook登录时,您将从Facebook上的应用程序仪表板获得应用程序密码。

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

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

This documentation page describes how to use the signed authentication.不会被标题中的“游戏”吓倒,它在任何web应用程序上都运行得很好。

您可以使用其他OAUTH提供程序,以与FB登录相同的方式实现一些功能,而不是只允许Facebook进行SSO。

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

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

客户端在每次请求时将此令牌提供给RESTful应用程序接口,服务器将检查签名。就像Facebook的SSO一样。

仍然有一个会话,但它可以在完全不同的机器上维护。此服务可以通过您的RESTful应用程序接口独立于服务器进行扩展。

但是,请记住,这种方法很容易受到中间人攻击和重放攻击。在没有https的情况下使用可能并不明智。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18168471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档