Rails Rails 5.2 中的 Credentials 和 Active Storage

jesktop · 2018年04月27日 · 最后由 yu7272yu 回复于 2020年03月05日 · 10865 次阅读
本帖已被管理员设置为精华贴

看到很多朋友们对 Rails 5.2 里的新东西,感觉云里雾里的,不太清楚它们究竟为我们提供了什么便利,所以我这里主要讲讲新版本中的 Credentials 和 Active Storage。

为什么使用 credentials?

先回顾在 5.2 版本以前,我们为了处理很多私密的信息,需要在.gitignore里加入多少的 yml 文件,有secrets.ymldatabase.ymlcable.yml,甚至会加入一些自定义的配置文件,如:application.yml

然后在部署配置中:

set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/cable.yml'...)

而我们升级到 Rails 5.2 后,很可能,只需要在.gitignore加入master.key一个文件,就可以处理所有的私密信息了。究竟credentials.yml.encmaster.key是怎么办到的呢?

把私密信息放入 credentials 中

因为我们在使用credentials.yml.enc后,可以把所有私密的信息都放到里面,然后通过master.key进行解密。所以当我们团队在一起完成一个项目时,需要分享master.key文件,但是考虑到安全的问题,不要把master.key上传到 git 的仓库中。

当我们打开credentials.yml.enc发现内容是一串随机串,如下:

qEbH/+fadmlPVeMVgFvpwk4ADadW2LbMkzMKJKkHrZeFNooiKKJvOoe5YJlbab1wJLHL77nSohvEm6MYnl9krXLFnDG0iSWm/svtipruMCc1FVfhSpmXSvLNJI1RUk2VeZCFjYkT8/PG4N7oj1OLrSq4yeRsbKTrS/3izcMm9ndJkcd4/wR7WAMReQSRGt5YGNZ4E3Jt9Wgg7ls2okZcwxEv/3brdgIyHrmfyEWb50YSe5oDDyscfRNX70uwZieSVGn99fFcexYUL8F0dxSrVNaix/h/UAeApq6Ifhs0/p9eXk0349f8dEMFkp5A3I4j0ubgjZ/ncdLTct37OxxhfucWukCtP6oSFvpC+5ma2epjjTSJM25+Vv3GQy7xfSdwbsEq8jm3tqT/zGr2M9iRuEX+LJrxzhDHnHC0--jQ+G6M9HWGe7zlFb--ltdsqYuI+4O8cqw/bcJRJw==

非常棒,secret_key_base之类的信息都在里面安全的保护着,可是如果我要修改里面的内容,怎么办?我们不可能直接修改加密后的内容啊。

不要着急,Rails 这里给我们提供了一个方便的方法:EDITOR="mate --wait" bin/rails credentials:edit。当然,EDITOR 的信息需要根据我们使用的工具进行调整。

EDITOR=vim bin/rails credentials:edit  # 使用VIM编辑
EDITOR="subl --wait" bin/rails credentials:edit  # 使用Sublime编辑

输入命令后,我们可以清楚的看到里面的内容:

# aws:
#   access_key_id: 123
#   secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 0b4d8892f41d7b89127b3ad997ca9ca581fe7f84bf890c85095b635c651a9de00edd1032aeb377a5753f0236e526cb61d995d01fc3d52bb5644a33dbfbc69335

所以我们就可以在里面输入需要加密的信息,例如输入在生产环境里,数据库的密码:

...
production:
  database:
    database: project
    password: 9f797275f3f
...

然后在我们需要用到这些加密信息的地方,调用:

Rails.application.credentials[Rails.env][:database][:database]
Rails.application.credentials[Rails.env][:database][:password]

剩下部署的时候,就记得把master.key放到服务器里,不要弄丢了。

如何使用 Active Storage

因为 Active Storage 和 Rails 结合紧密,所以使用起来很方便。在项目中运行rails active_storage:install,就会发现生成了一个数据迁移的文件,里面会给我们加入两个表,分别是active_storage_blobs(储存文件信息)active_storage_attachments(与业务表的多对多关系)

如果我们需要在Project模型中,保存image信息时,就不需要像使用CarrierWave时,在Project中另外添加字段,因为Active Storage会把文件信息直接保存到active_storage_blobsactive_storage_attachments中,我们只需要在Project的模型中加入:

has_one_attached :image  ## 一对一关系 或
has_many_attached :images  ## 一对多关系

在控制器里的参数保护也不需要做特殊的处理,只需要保持正常的设置就可以了。

params.require(:project).permit(..., :image)   # 一对一关系 或
params.require(:project).permit(..., images: [])   # 一对多关系

##通过 Active Storage 上传的文件会保存在哪里? 通过config/storage.yml,我们可以看到:

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

默认的testlocal是保存在本地的 Disk 中的,local默认把文件保存在storage文件夹中,所如果我们想要把文件保存在 public 内,可以修改成:

root: <%= Rails.root.join("public/storage") %>

当然无论我们保存在什么位置,记得把该目录加入到.gitignore中。

那么在开发环境中,它是如何知道使用local配置的呢?在config/environments/development.rb中,我们可以看到:

# Store files locally.
config.active_storage.service = :local

所以,如果我们生产环境也希望保存在Disk的话,只需要修改config/environments/production.rb即可,当然我们会建议使用云服务,因为结合Active Storage可以让一切变得很简单,例如保存在aws,只需要:

# config/environments/production.rb
# Store files on Amazon S3.
config.active_storage.service = :amazon

# config/storage.yml
amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""

在前端,可以看到application.js里加入了//= require activestorage,通过activestorage可以使用<%= form.file_field :image, direct_upload: true %>,全交给客户端直接往云服务器上传文件,避免经过服务器。

同时,如果需要调整图片尺寸大小时,我们加入gem 'mini_magick'后,直接在页面就可以对图片尺寸进行处理:

<%= image_tag project.image.variant(resize: "100x100") %>

国内云服务的Active Storage相关 gem:
https://github.com/mycolorway/activestorage_qiniu
https://github.com/doabit/activestorage_upyun
https://github.com/huacnlee/activestorage-aliyun

参考:
Rails 5.2: Active Storage and beyond
Active Storage Environment-Specific Credentials
Encrypted Credentials — A new way to use Secrets in Rails 5.2
Rails 5.2 credentials

原文:https://www.jianshu.com/p/b0312d926899

好的分享。继续前进学习

凑巧最近两天试了 active_storage. 如果是使用直传的话需要注意一下 cors 的限制,

aws 以及类似的服务 (digitalocean 的 spaces),在设置 bucket 的 cors 的时候 ,需要将域名允许跨域,且其 headers 允许里加入* 后才行.(我是在 digitalocean 测的,他的 cors custom headers 似乎只能配* 而不能配置 aws-*)

ps 我觉得最炫酷的还是提供不同 storage 的同步功能。

求个 credentials 的实践方案。

如果来个 Active Storage 的完整实例就完美了,其中的坑不知有哪些啊!

也就说 .env 可以不用咯 汪汪汪🐶

最近试了一下这个功能,使用的是 Disk 方式存储本地,但是存储的文件名是乱的,无法区分,有什么方法可以指定每张图片具体存储的路径呢?

huacnlee 将本帖设为了精华贴。 05月28日 10:31

感谢分享,Active Storage 的部分懂了。Credentials 依然没懂(我去看看英文资料去)

我在使用 Active_Storage 的时候,遇到了一个奇怪问题。 这么多年来,一直都在使用七牛云,做了设置: storage.yml 里面

qiniu:
    service: Qiniu
    access_key: <%= Rails.application.credentials.dig(:qiniu, :access_key) %>
    secret_key: <%= Rails.application.credentials.dig(:qiniu, :secret_key) %>
    bucket: <%= Rails.application.credentials.dig(:qiniu, :bucket) %>
    domain: <%= Rails.application.credentials.dig(:qiniu, :domain) %>

development.rb 里面

config.active_storage.service = :qiniu

_form.html.erb 里面

<%= form.file_field :image, direct_upload: true%>

在上传文件的时候,却得到了这样的提示:

NameError (Cannot load `Rails.config.active_storage.service`:
uninitialized constant ActiveStorage::Service::QiniuService::Qiniu):

使用 local 的时候,没有问题。 七牛的全套设置,是在其他项目里面一直在用的,肯定没有问题。

请问我少设置了什么吗?

当我添加了: config.active_storage.analyzers = [ ActiveStorage::Analyzer::QiniuImageAnalyzer, ActiveStorage::Analyzer::QiniuVideoAnalyzer ] 之后,显示 analyzers 失败。

我很喜欢用 CarrierWave 里面的 remote_url,直接抓取外面的资源,现在怎么搞? 另外,原来 carrierwave 里面,是在上传的时候,做图像处理的,还可以添加水印、圆角什么的,现在怎么搞?是不是都要到显示的时候来处理?这样的话,是不是每次显示的时候都要运算,原来是分成不同的版本存下来的,显示的时候直接调用就好了。

另外,询问一下,mongoid 上怎么用这个东西?CarrierWave 是有 mongoid 的整合 gem 的。

hechian [该话题已被删除] 提及了此话题。 08月21日 13:09
jicheng1014 回复

@jicheng1014 怎么同步不同 storage,比如把 local 存储的图片同步到 s3 上

我使用了直传阿里云 oss,奇怪的是没有数据库中没有生成 active_storage_attachments 记录,这是为什么呢?转成本地存储一切正常啊

执行这样命令后,没有显示编辑内容,而是报了错,请问各位大神这是为啥呢?

EDITOR=vi bin/rails credentials:edit

ruby-2.6.0/gems/activesupport-5.2.3/lib/active_support/message_encryptor.rb:201:in `final': OpenSSL::Cipher::CipherError

ruby-2.6.0/gems/activesupport-5.2.3/lib/active_support/message_encryptor.rb:206:in `rescue in _decrypt': ActiveSupport::MessageEncryptor::InvalidMessage (ActiveSupport::MessageEncryptor::InvalidMessage)
karidyang 回复

我遇到了一样的问题,解决了吗

@selenium 解决了,是因为我换了台电脑,master.key 和创建项目的时候不一致导致的。

23 楼 已删除
karidyang 回复

谢谢,我也找到问题在哪儿了,我把 credentials.yml.enc 和 master.key 都删除了,重新执行 EDITOR=vim bin/rails credentials:edit 就好了

Fighting_3 回复

我想请问一下,你是怎么找到这个路径的,我不知道怎么找到这个路径。。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号