让我们看看 shopify 以及他们是如何做到的。
Shopify 区分两种情况:
案例 #1 - 租户的域具有 SSL
租户虚拟域名:https://www.secure.shop
注册表单指向https://www.secure.shop/signup,成功注册后我会收到302 Found,它将我重定向到https://www.secure.shop并设置会话cookie。
-> POST https://www.secure.shop/signup, (signup data)
<- 302 Found
Location: https://www.secure.shop
Set-Cookie: _session_id=eba010959d42ec1b734c7bc335ca13cb; path=/;secure; HttpOnly
-> GET https://www.secure.shop
<- 200 OK
登录表单指向https://www.secure.shop/login,成功登录后,我得到一个302 Found,它将我重定向到https://www.secure.shop并设置一个会话cookie。
-> POST https://www.secure.shop/login, (credentials)
<- 302 Found
Location: https://www.secure.shop
Set-Cookie: _session_id=238aba8be83ceb3ba4a8ae4d94b1b026; path=/;secure; HttpOnly
-> GET https://www.secure.shop
<- 200 OK
签出通过https://www.secure.shop/checkout进行。
注销指向https://www.secure.shop/logout,发生的情况是:
-> GET https://www.secure.shop/logout
<- 302 Found
Location: https://www.secure.shop
Set-Cookie: _session_id=3b778bb251e170a9e3b1cd8794862203; path=/; secure; HttpOnly
-> GET https://www.secure.shop
<- 200 OK
结论:一切都在租户的域下运行。一个会话 cookie,不涉及任何魔法。
案例 #2:租户的域没有 SSL
租户虚拟域名:http://www.insecure.shop
注册表单指向https://insecureshop.myshopify.com/account,当我创建新帐户时,会发生以下情况:
-> POST https://insecureshop.myshopify.com/account, (signup data)
<- 302 Found
Location: http://www.insecureshop.com/account?sid=514d3e699fd55ddb7c12398405e65abf
Set-Cookie: _secure_session_id=c31d544b27ee8a49b5a6cf9e303e6829; path=/; secure; HttpOnly
-> GET http://www.insecureshop.com/account?sid=514d3e699fd55ddb7c12398405e65abf
<- 200 OK
Set-Cookie: _session_id=18d5f07e1e61d8707e111879860abad6; path=/; HttpOnly
登录表单指向https://insecureshop.myshopify.com/account/login,发生的情况是:
-> POST https://insecureshop.myshopify.com/account/login, (credentials)
<- 302 Found
Location: http://www.insecure.shop/account?sid=a232e58b8cb9fb4936ddf889ab7e73e4
Set-Cookie: _secure_session_id=d54a653cf4fcb66b831968e9e669b005; path=/; secure; HttpOnly
-> GET http://www.insecure.shop/account?sid=a232e58b8cb9fb4936ddf889ab7e73e4
<- 200 OK
Set-Cookie: _session_id=44e041cdbcb64d2a2281bb64db52ada0; path=/; HttpOnly
结帐通过https://checkout.shopify.com
进行
注销指向http://www.insecure.shop/account/logout,发生的情况是:
-> GET http://www.insecure.shop/account/logout
<- 302 Found
Location: https://insecureshop.myshopify.com/account/logout?sid=d6c774d39307def7f772de31031c665c
Set-Cookie: _session_id=8dfb0a130d6f479d1af3a52c40ad3be6; path=/; HttpOnly
-> GET https://insecureshop.myshopify.com/account/logout?sid=d6c774d39307def7f772de31031c665c
<- 302 Found
Location: http://www.insecure.shop
Set-Cookie: _secure_session_id=18fcde259616586f89831399cc9c2425; path=/; secure; HttpOnly
-> GET http://www.insecure.shop
<- 200 OK
结论:在不安全的商店的情况下,一切都完成了两次,两个单独的(并且不同的!)会话在租户的不安全域上创建一次,在租户的 myshopify 子域上创建一次。两个会话都指向后端的相同用户记录。
凭据以加密方式发送,一次性令牌通过重定向传递到不安全域,然后在不安全域上创建经过身份验证的会话。此令牌以纯文本形式传输。
你首先想到的可能是:
如果中间人截获该令牌并劫持会话怎么办?
好吧,攻击者将在http://www.insecure.shop 上进行身份验证,但不会在https://insecureshop.myshopify.com 上进行身份验证。
如果我们尝试聪明一点并使用带有 CORS 的 AJAX 请求并使用 JavaScript 手动设置会话 cookie,那么不会发生使用魔法令牌的重定向
这也无济于事,因为会话 cookie 本身一直以纯文本形式传输,因此会话无论如何都可能被劫持。更糟糕的是,我们只有一个会话。
为什么他们对同一个用户使用两个不同的会话/会话 ID?
这就是神奇之处,您在http://www.insecure.shop 上的会话很容易被攻破,但是您在https://insecureshop.myshopify.com 上的会话不会被攻破,因为攻击者不知道会话 ID,因为 cookie 是通过 SSL 和会话 ID 传输的与“不安全”的不同。
但攻击者仍然可以在 http://www.insecure.shop 上滥用我的帐户
没错,但他能做什么?他可以将产品添加到您的购物车、阅读您的个人资料等,但他不能进行结帐并从您的信用卡中扣款。为什么?因为结帐通过https://insecureshop.myshopify.com 的安全部分,他没有会话cookie,因此未经身份验证。
但如果攻击者很聪明,他可以在不安全和安全部分更改密码并重新登录
如果您添加适当的措施,即要求用户输入密码以进行任何配置文件更改,则不会。攻击者不知道凭据,因为它们是通过 SSL 传输的。
还是没有更好的解决方案
有 - 在任何地方都使用 HTTPS,例如 CloudFlare 可以很容易地将 SSL 放在客户的域前面。这既可以减少您实施的开销,又可以为您的客户和客户的客户增加价值。双赢局面。
您不必为此使用 CloudFlare 等第三方解决方案,因为您负责 - 所有流量都通过您的服务器/前端代理(例如 nginx)。您可以为您的客户管理 SSL 证书并向他们收费,但是由于每个域都需要自己的证书,因此这对于记帐和配置都变得相当麻烦。
更新(重要)
请注意不安全情况下的细微差别,两个 cookie 的名称为 _session_id 和 _secure_session_id。这是有充分理由的,因为两个会话都存在于同一个 rails 实例上,并且它们可以互换使用,这是一件坏事。我认为他们正在做的是在会话上设置一个标志,是否会话是通过安全通道创建的,并在之前添加适当的操作,例如
before_action :require_secure_session, only: :checkout
def require_secure_session
head :unauthorized unless session[:is_secure_flag]
end
来源:
店铺示例取自http://wemakewebsites.com/blog/80-best-shopify-stores-for-ecommerce-inspiration,https 一个是#79,http 一个是#23。使用的工具:Chrome 开发者工具(网络标签)、cURL。