仅适用于安全页面的安全回形针 URL
我正在尝试找到使回形针网址安全的最佳方法,但仅限于安全页面。
例如,显示存储在 S3 中的图像的主页为 http://mydomain.com,图像 url 为 < a href="http://s3.amazonaws.com/mydomainphotos/89/thisimage.JPG?1284314856" rel="noreferrer">http://s3.amazonaws.com/mydomainphotos/89/thisimage.JPG?1284314856< /a>.
我有像 https://mydomain.com/users/my_stuff/49 这样包含图像的安全页面存储在S3中,但S3协议是http而不是https,因此用户会从浏览器收到警告,说页面上的某些元素不安全,等等等等。
我知道我可以在模型中指定 :s3_protocol ,但这使得一切都安全,即使没有必要。因此,我正在寻找将协议动态更改为 https 的最佳方法,仅适用于安全页面。
一种(可能是坏的)方法是创建一个新的 url 方法,例如:
def custom_url(style = default_style, ssl = false)
ssl ? self.url(style).gsub('http', 'https') : self.url(style)
end
需要注意的一件事是我正在使用 ssl_requirement 插件,因此可能有一种方法可以将其与该插件结合起来。
我确信有一些我忽略的简单、标准的方法可以做到这一点,但我似乎找不到它。
I'm trying to find the best way to make paperclip urls secure, but only for secure pages.
For instance, the homepage, which shows images stored in S3, is http://mydomain.com and the image url is http://s3.amazonaws.com/mydomainphotos/89/thisimage.JPG?1284314856.
I have secure pages like https://mydomain.com/users/my_stuff/49 that has images stored in S3, but the S3 protocol is http and not https, so the user gets a warning from the browser saying that some elements on the page are not secure, blah blah blah.
I know that I can specify :s3_protocol in the model, but this makes everything secure even when it isn't necessary. So, I'm looking for the best way to change the protocol to https on the fly, only for secure pages.
One (probably bad) way would be to create a new url method like:
def custom_url(style = default_style, ssl = false)
ssl ? self.url(style).gsub('http', 'https') : self.url(style)
end
One thing to note is that I'm using the ssl_requirement plugin, so there might be a way to tie it in with that.
I'm sure there is some simple, standard way to do this that I'm overlooking, but I can't seem to find it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果现在有人偶然发现这一点:自从 2012 年 4 月!只需在初始化程序中编写:
或在模型中使用 s3_protocol 选项。
感谢@Thomas Watson 发起此活动。
If anyone stumbles upon this now: There is a solution in Paperclip since April 2012! Simply write:
in an initializer or use the
s3_protocol
option inside your model.Thanks to @Thomas Watson for initiating this.
如果使用 Rails 2.3.x 或更高版本,您可以使用 Rails 中间件来过滤响应,然后再将其发送回用户。通过这种方式,您可以检测当前请求是否是 HTTPS 请求,并相应地修改对 s3.amazonaws.com 的调用。
创建一个名为
paperclip_s3_url_rewriter.rb
的新文件,并将其放置在服务器启动时加载的目录中。lib
目录可以工作,但许多人更喜欢创建一个app/middleware
目录并将其添加到 Rails 应用程序加载路径中。将以下类添加到新文件中:
然后只需注册新的中间件:
Rails 2.3.x:将下面的行添加到
Rails::Initializer.run
块开头的environment.rb中。< br>Rails 3.x:将以下行添加到 Application 类开头的 application.rb 中。
更新:
我刚刚编辑了答案并在 if 语句中添加了对
response.is_a?(ActionController::Response)
的检查。在某些情况下(可能与缓存相关),响应对象是一个空数组(?),因此在调用request
时会失败。更新2:
我编辑了上面的机架/中间件代码示例,还更新了
Content-Length
标头。否则 HTML 正文将被大多数浏览器截断。If using Rails 2.3.x or newer, you can use Rails middleware to filter the response before sending it back to the user. This way you can detect if the current request is an HTTPS request and modify the calls to s3.amazonaws.com accordingly.
Create a new file called
paperclip_s3_url_rewriter.rb
and place it inside a directory that's loaded when the server starts. Thelib
direcotry will work, but many prefer to create anapp/middleware
directory and add this to the Rails application load path.Add the following class to the new file:
Then just register the new middleware:
Rails 2.3.x: Add the line below to environment.rb in the beginning of the
Rails::Initializer.run
block.Rails 3.x: Add the line below to application.rb in the beginning of the Application class.
UPDATE:
I just edited my answer and added a check for
response.is_a?(ActionController::Response)
in the if statement. In some cases (maybe caching related) the response object is an empty array(?) and hence fails whenrequest
is called upon it.UPDATE 2:
I edited the Rack/Middleware code example above to also update the
Content-Length
header. Otherwise the HTML body will be truncated by most browsers.在控制器类中使用以下代码:
您当然可以将其很好地包装到方法中。
Use the following code in a controller class:
You can of course wrap this up nicely into a method.
仅供参考 - 上面的一些答案不适用于 Rails 3+,因为 ActionController::Response 已被弃用。使用以下命令:
end
并确保将中间件添加到堆栈中的合适位置(我在 Rack::Runtime 之后添加了它)
FYI - some of the answers above do not work with Rails 3+, because ActionController::Response has been deprecated. Use the following:
end
And make sure that you add the middleware in a good place in the stack (I added it after Rack::Runtime)