Posted by
XDite曾經在「以 ROR 打造網站,設計盲點所引發的惡搞危機」這篇文章中提到Rails的scaffold所建立出來的程式(或說開發者很習慣直接以id操作Model),由於在URL上是直接以流水號的方式呈現,我們便可以利用一些簡單的程式爬完某個網站的特定頁面,來取得所有的文章、所有的使用者頁面。
事實上XDite應該是有在另外一場活動提過因應的對策,雖然我沒抓下來聽,不過我猜應該是改變Controller的設計方式,以亂碼或是其他方式來產生URL。
首先在Table裡面加上「permalink」這個column,如果你是要在既有的table上新增,可以使用migration來新增欄位(當然你也可以砍掉重練XD)
class AddPermalink < ActiveRecord::Migration
def self.up
add_column :posts, :permalink, :string
add_index :posts, :permalink, :unique => true
end
def self.down
remove_index :posts, :permalink
remove_column :posts, :permalink
end
end
接下來在Model裡面定義permalink的產生方式
class Post < ActiveRecord::Base
before_create :generate_permalink
protected
def generate_permalink
# 定義permalink的產生方式
self.permalink = Time.now.strftime("%Y-%m-%d_") + rand(100000).to_s
end
end
這邊我是用時間加亂數的方式產生permalink,事實上這樣的寫法還是有可能重複,不如用SHA或MD5的方式來產生Permalink也不錯(雖然長了點)。
class Post < ActiveRecord::Base
before_create :generate_permalink
protected
def generate_permalink
# 用標題+時間進行md5的編碼
require 'digest/md5'
self.permalink = Digest::MD5.hexdigest(self.title + Time.now.to_s)
end
end
往後在連結可以使用:
link_to post.title,
:controller => "post",
:action => "show",
:id => post.permalink
在Controller裡面Action的寫法則是:
class PostController < ApplicationController
def show
@post = Post.find_by_permalink(params[:id])
end
end
多謝,受益良多。
您的before_create callback是不是應該設成protected比較好?