这种 Ruby eval 方法的使用真的很危险吗?如果是,还有什么替代方法? (Rails)
Is this use of a Ruby eval method really dangerous, and if so what's the alternative? (Rails)
好的,所以我在我的 Rails 应用程序中使用 AASM 来管理我的用户模型周围的工作流。在视图层中,我想做一个小下拉菜单,显示给定用户的所有可用转换,并在单击时执行该转换,它会根据用户所处的状态动态调整。它工作正常。这是基本实现:
views/admin/users/index.html.erb:
<% user.available_transitions.each do |t| %>
<%= link_to(t.to_s.humanize, eval("#{t}_admin_user_path(user)"), class: 'dropdown-item', :method => :post) %>
<% end %>
在路由文件中:
namespace :admin do
...
resources :users do
member do
post 'apply'
post 'invite_to_interview'
post 'approve_for_training'
...
end
end
end
每一个在控制器中都有对应的动作。真的不值得一一列出,他们只是调用适当的转换,例如 @user.invite_to_interview!
和一些 begin/rescues
来捕获由于守卫等引起的无效转换
Brakeman 对视图中的 eval()
方法很生气。我不是 100% 确定为什么它会为此烦恼 - 它只是将所有 eval()
方法视为邪恶吗?传递到方法中的对象 (t
) 不是用户输入,它基于状态机提供的转换。我不知道这怎么可能是一个漏洞?也许这是我对一些基本概念缺乏理解......
所以真的有两个问题:
- 我应该担心吗?为什么?这里的潜在问题是什么?如果有问题,我应该如何解决?
- 总的来说,这感觉是一种麻烦的实现方式,因为每次添加新状态、转换等时,您都必须创建控制器操作和路由条目。有没有更好的方法来实现这个?也许控制器中的某种通用
transition
操作已传入转换?看起来更干净,有兴趣听听是否有其他人采用这种方法。
谢谢!感谢您的帮助。
Is there a better method for implementing this? Maybe some kind of generic transition action in the controller that has the transition passed in? Seems cleaner, interested to hear if anyone else has taken this approach.
按照以下方式行事怎么样:
<% user.available_transitions.each do |t| %>
<%= link_to t.to_s.humanize, admin_user_path(user, transition: t), class: 'dropdown-item', method: :patch %>
<% end %>
然后,在 AdminUsersController
的 update
方法中(或 admin_user_path
使用 patch
HTTP 动词解析的任何地方),您可以测试是否存在transition
参数并据此采取行动。正如您所说,您可以包括一些 begin/rescues 以捕获由于守卫等引起的无效转换
这样一来,您对所有链接只有一个操作。
好的,所以我在我的 Rails 应用程序中使用 AASM 来管理我的用户模型周围的工作流。在视图层中,我想做一个小下拉菜单,显示给定用户的所有可用转换,并在单击时执行该转换,它会根据用户所处的状态动态调整。它工作正常。这是基本实现:
views/admin/users/index.html.erb:
<% user.available_transitions.each do |t| %>
<%= link_to(t.to_s.humanize, eval("#{t}_admin_user_path(user)"), class: 'dropdown-item', :method => :post) %>
<% end %>
在路由文件中:
namespace :admin do
...
resources :users do
member do
post 'apply'
post 'invite_to_interview'
post 'approve_for_training'
...
end
end
end
每一个在控制器中都有对应的动作。真的不值得一一列出,他们只是调用适当的转换,例如 @user.invite_to_interview!
和一些 begin/rescues
来捕获由于守卫等引起的无效转换
Brakeman 对视图中的 eval()
方法很生气。我不是 100% 确定为什么它会为此烦恼 - 它只是将所有 eval()
方法视为邪恶吗?传递到方法中的对象 (t
) 不是用户输入,它基于状态机提供的转换。我不知道这怎么可能是一个漏洞?也许这是我对一些基本概念缺乏理解......
所以真的有两个问题:
- 我应该担心吗?为什么?这里的潜在问题是什么?如果有问题,我应该如何解决?
- 总的来说,这感觉是一种麻烦的实现方式,因为每次添加新状态、转换等时,您都必须创建控制器操作和路由条目。有没有更好的方法来实现这个?也许控制器中的某种通用
transition
操作已传入转换?看起来更干净,有兴趣听听是否有其他人采用这种方法。
谢谢!感谢您的帮助。
Is there a better method for implementing this? Maybe some kind of generic transition action in the controller that has the transition passed in? Seems cleaner, interested to hear if anyone else has taken this approach.
按照以下方式行事怎么样:
<% user.available_transitions.each do |t| %>
<%= link_to t.to_s.humanize, admin_user_path(user, transition: t), class: 'dropdown-item', method: :patch %>
<% end %>
然后,在 AdminUsersController
的 update
方法中(或 admin_user_path
使用 patch
HTTP 动词解析的任何地方),您可以测试是否存在transition
参数并据此采取行动。正如您所说,您可以包括一些 begin/rescues 以捕获由于守卫等引起的无效转换
这样一来,您对所有链接只有一个操作。