Essentail Rails Design Pattern

Write Good Rails Code

不使用 RESTful

Abuse : 厭惡使用 RESTful

1
 # match ':controller(/:action(/:id(.:format)))'
  • 程式碼失去組織性
  • 嚴重的 security issue

免跨站偽造請求 Cross-site request forgery

  • 所有讀取、查詢性質操作,都應該用GET
  • 修改或刪除到資料的,則要用POST、PUT或DELETE
  • 所有的POST請求,都必須加上一個安全驗證碼

內建機制

app/controllers/application_controller.rb

1
2
3
class ApplicationController < ActionController::Base
  protect_from_forgery
end

app/views/layout/application.html.erb

1
<%= csrf_meta_tag %>
1
 # match ':controller(/:action(/:id(.:format)))'
  • 硬幹就失去天然屏障了,任何 action 都可以 get
1
   <img src="/posts/delete_all">

安全性:透過對資源操作的限制,可以阻擋不安全的操作。

需要安全性的操作行為,需要透過表單的 POST,才能執行。

然而開發者可能只會記得在 .htaccess 加入對 /question/1/delete 的 URL mapping,卻忘記這個動作需要關閉 GET,否則 hacker 就可以透過製造惡意的連結,誘騙管理者誤開連結,砍除大量的資料。

1
2
<form accept-charset="UTF-8" action="/post/delete_all" method="post" novalidate="novalidate">
</form>

而在 Rails 中,因為採用 REST,對於一個資源送 GET / POST / PUT / DELETE 都會對應到不同的 action,所以不會有這樣的情形發生。

修改文章的表單

1
2
3
4
5
6
7
8
9
10
<h1>Editing post</h1>
<%= form_for @post , :url => post_path(@post) , :html => {:method => :put} do |f| %>
    <%= f.error_messages %>
    <div><%= f.text_field :subject %>
    <div><%= f.text_area :content %></div>
    <%= f.submit "Submit", :disable_with => 'Submiting...' %>
<% end -%>

<%= link_to 'Show', post_path(post) %> |
<%= link_to 'Back', posts_path %>

Comments