rails 加密_在Rails应用程序中测试签名和加密的Cookie

rails 加密

最近,我一直在对我维护的gem进行测试重构,我需要测试它是否在正确的时间设置了正确的cookie。 但是,宝石中使用的cookie是已签名的cookie,这对我造成了轻微的打ic。 我以前从未测试过签名Cookie中的值,而且还不清楚该怎么做。

所以我想我会分享我发现的内容,以防万一。

Rails上的Cookie

在Rails应用程序中,可以使用三种Cookie:
简单会话cookie,签名cookie和加密cookie。 您可以
通过使用控制器中的cookies对象来设置其中任何一个,如下所示:

class CookiesController <  ApplicationController
  def index
    cookies[ "simple" ] = "Hello, I am easy to read."
    cookies.signed[ "protected" ] = "Hello, I can be read, but I can't be tampered with."
    cookies.encrypted[ "private" ] = "Hello, I can't be read or tampered with."
  end
end

简单的饼干

简单的cookie由纯文本组成。 如果您在浏览器中检查了上面称为“简单”的cookie,您将看到文本“您好,我很容易阅读”。

简单的cookie可以存储真正无关紧要的数据。 最终用户可以阅读和更改它,并且您的应用程序不会受到影响。

签名的cookie

签名的cookie不会以纯文本形式发送到浏览器。 取而代之的是,它们由有效载荷和签名组成,并由两个破折号--分隔。 在破折号之前,有效载荷是基数为64的编码数据 。 要读取数据,您可以基于64位对其进行解码。 此数据不是秘密数据,但是由于Cookie的第二部分是签名,因此不能被篡改。

通过获取应用程序的secret_key_base和cookie中的数据的HMAC SHA1摘要来创建签名。 如果您尝试读取Cookie时更改了cookie的内容,则签名将不再与内容匹配,并且Rails将返回nil 。 在ActiveSupport::MessageVerifier这全部由ActiveSupport::MessageVerifier处理。 从上面可以看到,您不必担心,可以将cookies.signed对象当作哈希来对待。

签名的cookie对于用户可以读取的数据很有用,但是当您再次将其返回给服务器时,需要信任的是相同的。

加密的cookie

加密的cookie会更进一步,并加密cookie中的数据,然后对其进行签名。 这由ActiveSupport::MessageEncryptor处理,这意味着如果没有secret_key_base您将无法读取或写入此Cookie。 值得庆幸的是,您无需担心加密问题,使用cookies.encrypted对象,您可以将加密的cookie设置为常规哈希来设置。

加密的cookie对于要与用户存储但不希望它们或任何人读取的私有数据很有用。

测试cookie

假设我们现在要测试上面看到的控制器。 我们想
确保我们所有的Cookie均已正确设置。 测试可能看起来
像这样的东西:

class CookiesControllerTest < ActionDispatch::IntegrationTest
  test "should set cookies when getting the index" do
    get root_url
    assert_response :success
    assert_equal "Hello, I am easy to read." , cookies[ "simple" ]
    assert_equal "Hello, I can be read, but I can't be tampered with." , cookies[ "protected" ]
    assert_equal "Hello, I can't be read or tampered with." , cookies[ "private" ]
  end
end

或使用RSpec Rails:

RSpec.describe CookiesController,type: :request do
  it "should set cookies when getting the index" do
    get root_url
    expect(response).to have_http_status( :success )
    expect(cookies[ "simple" ]).to eq( "Hello, I am easy to read." )
    expect(cookies[ "protected" ]).to eq( "Hello, I can be read, but I can't be tampered with." )
    expect(cookies[ "private" ]).to eq( "Hello, I can't be read or tampered with." )
  end
end

但这将在测试签名的cookie时失败,并且也不会通过加密的cookie。 如果这些cookie已签名或加密,则不能直接从罐子中调用这些cookie。

您可能会认为应该针对Cookie的signedencrypted版本进行测试,如下所示:

assert_equal"Hello, I can be read, but I can't be tampered with." , cookies.signed[ "protected" ]
    assert_equal "Hello, I can't be read or tampered with." , cookies.encrypted[ "private" ]

那也不行。 至少如果您使用的是当前推荐的测试控制器的方法(在Minitest中使用ActionDispatch::IntegrationTest或在RSpec中type: :request ActionDispatch::IntegrationTest type: :request ,则它不起作用。

如果您使用的是旧样式ActionController::TestCasetype: :controller ActionController::TestCase type: :controller测试,则cookies.signedcookies.encrypted将起作用。 如果您的应用程序具有较早的样式测试,请继续阅读以防万一您决定重构它们以使其与当前的Rails方式保持一致。

通过上述测试, cookies对象实际上是Rack::Test::CookieJar的实例,该实例不了解您的Rails应用程序机密。

那么我们如何测试这些cookie?

这就是我接触到的宝石的所在。 我需要测试签名cookie的结果,但是我有一个Rack::Test::CookieJar对象。 好消息是,我们可以重新使用Rails应用程序自己的ActionDispatch::Cookies::CookieJar来解码已签名的Cookie和解密已加密的Cookie。

为此,您ActionDispatch::Cookies::CookieJar使用测试中的request对象和cookie数据的哈希来实例化ActionDispatch::Cookies::CookieJar的实例。 然后,您可以在该Cookie罐上调用signedencrypted

所以现在测试看起来像:

class CookiesControllerTest < ActionDispatch::IntegrationTest
  test "should set cookies when getting the index" do
    get root_url
    assert_response :success
    assert_equal "Hello, I am easy to read." , cookies[ "simple" ]
    jar = ActionDispatch::Cookies::CookieJar.build(request, cookies.to_hash)
    assert_equal "Hello, I can be read, but I can't be tampered with." , jar.signed[ "protected" ]
    assert_equal "Hello, I can't be read or tampered with." , jar.encrypted[ "private" ]
  end
end

或规格看起来像:

RSpec.describe CookiesController,type: :request do
  it "gets cookies from the response" do
    get root_url
    expect(response).to have_http_status( :success )
    expect(cookies[ "simple" ]).to eq( "Hello, I am easy to read." )
    jar = ActionDispatch::Cookies::CookieJar.build(request, cookies.to_hash)
    expect(jar.signed[ "protected" ]).to eq( "Hello, I can be read, but I can't be tampered with." )
    expect(jar.encrypted[ "private" ]).to eq( "Hello, I can't be read or tampered with." )
  end
end

红色,绿色,零食

在这篇文章中,我们已经看到了如何在Rails中测试签名或加密的cookie。 希望您的测试套件运行为绿色,并且现在覆盖您的cookie。

我将回到我正在研究的重构中。 现在,这些Cookie已被删除,还有很多测试可以覆盖。

翻译自: https://hackernoon.com/testing-signed-and-encrypted-cookies-in-rails-application-358z369v

rails 加密

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值