草庐IT

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

coder 2024-07-28 原文

如果我有SPA(用BackboneJS开发的单页应用程序),并且想为其数据使用无状态RESTful后端API。我喜欢3rd party单点登录如何使用户变得如此简单,因此会喜欢它使用它。

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

最佳答案

免责声明:)

为我的产品实现了这样的事情,并分享了您的许多关注点和技术(尤其是使用100%无状态REST后端的Backbone SPA),我可以告诉您我对此有何看法,并明确表示这不希望成为“答案”,而是一个对话的开始者,可以从所进行的讨论中学到东西,因为我想我也有很多要学习的话题。

首先,我认为您应该100%无状态。 100%的意思是100%:)不仅您的API层应该是无状态的,而且整个应用程序(当然是客户端)也应该是无状态的。在不同的层(例如redis)上移动 session 只会稍微移动问题,但不能解决问题。一切(尤其是扩展)都将变得非常容易,您稍后将对这一决定表示感谢。

因此,是的,您需要对每个请求进行身份验证。但这并不意味着您必须每次都访问auth提供程序。我了解到的一件事是,允许用户通过FB/GitHub/What进行身份验证(无论如何,从现在开始,远程服务)只是缓解注册/登录之苦的一种手段,除此之外,别无其他。您仍然必须扩展您的用户个人数据库。当然,每个用户都将与“远程”用户相关联,但是在执行身份验证后不久,应用程序应引用“您的”用户,而不是“远程”用户(例如GitHub用户)。

执行

这是我已经实现的:

  • 我的API方法总是需要身份验证 token 。 auth token 是代表我系统用户的哈希,因此,当我调用POST /api/board?name=[a_name]&auth=[my_token]时,我知道谁在打电话,可以检查权限并将新创建的实体board与正确的用户关联。
  • 所述 token 与远程服务的 token 无关。计算它们的逻辑是特定于我的应用程序的。但是它映射了我的一个用户,该用户也映射到了一个远程用户,因此在需要时不会丢失任何信息。
  • 这是我通过远程服务对用户进行身份验证的方法。我按照服务文档中的说明实现远程身份验证。通常它是OAuth或类似OAuth的,这意味着最后我得到了代表远程用户的authToken。该 token 有两个用途:
  • 我可以使用它来调用作为用户
  • 的远程服务上的API方法
  • 我至少通过远程服务
  • 可以保证用户是它所说的用户
  • 用户通过远程服务对自己进行身份验证后,便会在系统中加载或创建匹配的用户。如果系统中不存在具有remote_id: GitHub_abc123的用户,则创建它,否则将其加载。假设该用户具有id: MyApp_def456。您还使用自己的逻辑创建了一个authToken,它将代表用户MyApp_def456并将其传递给客户端(cookies可以使用!)
  • 返回点1 :)


  • 笔记

    身份验证是在每个请求时执行的,这意味着您要处理散列和加密函数,这从定义上讲是很慢的。现在,如果您使用bcrypt进行20次迭代,这将终止您的应用程序。我使用它来存储用户登录时的密码,但随后为authToken使用了较不繁琐的算法(我个人使用了与SHA-256相当的哈希值)。这些 token 的生命周期很短(比平均破解时间还短),并且很容易在服务器计算机上进行计算。这里没有确切的答案。尝试不同的方法,进行测量并做出决定。相反,我确定的是,与 session 问题相比,我更喜欢这类问题。如果我需要计算更多或更快的哈希,则可以增加CPU的功耗。在 session 和群集环境中,您会遇到内存问题,负载平衡和粘性 session 问题或其他动荡的问题(redis)。

    毫无疑问,HTTPS是绝对必需的,因为authToken始终作为参数传递。

    关于javascript - SPA和SSO中无状态身份验证的性能(单点登录),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18168471/

    有关javascript - SPA和SSO中无状态身份验证的性能(单点登录)的更多相关文章

    1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

      我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

    2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

      我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

    3. ruby-on-rails - 跳过状态机方法的所有验证 - 2

      当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

    4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

      对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

    5. ruby - Net::HTTP 获取源代码和状态 - 2

      我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

    6. ruby-on-rails - 为模型创建状态属性 - 2

      我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,

    7. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

      s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

    8. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

      我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

    9. ruby - 在 ruby​​ 中生成一个进程,捕获 stdout,stderr,获取退出状态 - 2

      我想从ruby​​rake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调

    10. Ruby 的数字方法性能 - 2

      我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

    随机推荐