繁体   English   中英

WebSockets + PHP(Ratchet)登录系统

[英]WebSockets + PHP (Ratchet) login system

我知道如何使用PHP创建一个安全的登录系统,包括哈希,盐析和更复杂的安全措施等基础知识。

最近我一直在使用Ratchet和WebSockets。 我一直想知道是否可以使用WebSockets创建一个安全的注册/登录系统。

  1. 用户以表格形式输入数据。
  2. 数据经过验证和消毒。
  3. 密码是哈希值。
  4. 一切都通过WebSocket发送到服务器。
  5. PHP将其存储在MySQL数据库中并将密码的哈希值加密。
  6. PHP返回一个通过WebSocket完成注册的回调。
  7. 用户被授予访问该网站的权限。

我觉得它可能会奏效。 我的疑惑在这里:ws://协议有多安全? 如何确保登录用户后是记录的用户? 某种会话? 令牌?

是否有这样的框架/库/实现?

问题更多的是出于对新的(有点)技术的好奇心。 如果它不起作用,我只会去AJAX POST请求。 :)

不,使用PHP编写的任何当前WebSocket服务器都无法设置安全身份验证。

他们都缺乏TLS支持。 (甚至我的,虽然我有一个积极的开发分支致力于提供TLS支持。)

以下是使用WebSockets的安全身份验证系统所需的内容:

基本PHP安全第一:

  1. 始终通过TLS或其他安全传输系统进行传输。
  2. 使用bcrypt或scrypt(或将来更安全的系统)来哈希密码以便在数据库中存储。 即使是使用加密随机源生成的盐的拉伸SHA256密码现在也被认为是不安全的。
  3. 身份验证令牌(例如由PHP创建并存储在会话cookie中的会话令牌)必须在加密方面不可预测。
  4. 身份验证令牌不能用于非TLS流量或客户端脚本。 (严格执行安全标志并严格执行HttpOnly标志。)这明确表示用户无法安全地进行身份验证,除非他们处于https:和wss:mode。
  5. 会话数据必须存储在服务器上的安全目录或数据存储中。
  6. 作为身份验证的一部分重置会话令牌。 完全删除与旧会话ID关联的数据。

用于生成会话ID的PHP内置算法使用/ dev / urandom( 如果它在您的系统上可用) Windows用户不会获得加密随机会话ID,但由于大多数WebSockets实现都需要Posix环境,因此这不是问题。 如果滚动自己的会话ID生成器,请使用openssl_random_pseudo_bytes() ,并记住在安全性方面,推出自己的安全性是个坏主意。

此外,默认情况下,PHP会话cookie没有设置安全标志或HttpOnly标志。 在php.ini中更改这些,是的,这意味着人们无法对未使用安全连接的任何人进行身份验证 - 但无论如何都是如此,因为没有TLS,您无法确保任何人都是同一个用户请求请求,即使他们使用相同的会话ID和相同的IP。

并且,默认情况下,PHP会话保存路径是系统的临时目录。 这是任何人都可读写的。 因此,任何恶意进程,无论升级的权限如何,都可以访问和更改任何会话数据。 最少访问意味着只有Web服务器用户,并且在我们这些使用WebSockets的情况下,WS服务器的用户需要访问会话保存路径。

WebSockets特定身份验证:

会话cookie在握手期间可供WebSocket服务器使用。 这包括cookie设置HttpOnly标志的时间。 (在Windows上测试了最新公开的Chrome。)(安全标记尚未测试。在我的服务器上运行TLS时,给我几个月。如果安全cookie不可用,或者在非安全环境中可用,我将代表您亲自向浏览器供应商提出一个神圣的恶臭。)

这意味着具有经过身份验证的会话的人也可以在其WebSocket连接上进行预身份验证,而无需通过Web文档正文传递数据(无需将会话ID嵌入HTML或脚本标记中的数据中,这将然后通过开放的WS连接重新传输)。

至于使用WebSockets安全地验证某人......有一个巨大的警告。

由于WebSocket服务器同时连接了多个用户,因此传统的PHP会话意识被打破。 我们的意思是哪个会话?

因此,$ _SESSION超全局必须严格禁止,并且session_...()函数应该被认为是非常危险的。 唯一安全且有意义的会话函数是session_save_path()的只读版本,它告诉您在哪里可以找到会话文件, session_encode()session_decode()

要获取会话数据,您需要读取会话文件,通过session_decode()运行其内容,并将结果与​​该特定用户的特定连接相关联。 您还需要定期执行此操作,因为会话数据会在没有警告的情况下更改。 要将任何数据保存到会话中, session_encode()当然是您的朋友。 由于PHP不关心会话数据的竞争条件,因此您也不应该这样做。 只需读取文件,更改数据,然后写入文件,这一切都会很好。

这就带来了第一个真正的问题:为了进行安全身份验证,您需要在用户通过身份验证时重置会话令牌。 由于客户端Javascript无法写入HttpOnly cookie,因此无法在客户端更改会话ID。

当然,可以在现有会话数据内容易地更新用户是否被认证的状态。 这是相当微不足道的。 但是,因为我们持久化新的身份验证状态之前需要一个新的会话ID,并且新的会话ID必须立即对所有客户端的连接有效,我们无法通过WebSocket连接完全执行安全身份验证。

可能的解决方法是尽可能多地使用WebSockets(一旦PHP WS服务器支持TLS,就是这样):

  • 客户端通过WebSocket连接向服务器发送登录信息。
  • 服务器使用加密随机令牌进行响应。
  • 客户端通过WS连接使用salt进行响应,并通过AJAX请求使用哈希和盐渍版本的令牌进行响应。
  • 服务器验证salt匹配,并使用AJAX请求的脚本调用session_regenerate_id(true) ,并返回任何适当的响应(只要set-cookie:set-cookie: header)。
  • 服务器将其内部映射更新为用户的新会话ID。
  • 服务器完全丢弃一次性令牌,并自然记录任何尝试使用任何无效的一次性令牌。

(实现真正的Diffie-Hellman交换以建立真正的安全共享密钥可能是值得的。我不是安全专家;上述算法可能不像我想的那样安全,但因为它已经是在两个TLS隧道中,它应该是安全的。(https:隧道是独立的,与wss:tunnel不同,因此需要确认通过一个隧道发送的信息与通过另一个隧道发送的信息匹配,但不应要求保密。除了TLS已经提供的那个。))

底线:

是的,安全很难做到。 但这是值得的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM