[攻略] Ruby on Rails 與 SSL (https)
問題:該如何在 Ruby on Rails 導入 SSL (https) 的支援呢
以下分成 Mac OS X 與 Ubuntu Linux 的說明。
另外因為 mod_rails (Passenger) 在設定 SSL 方面格外簡單,因此假設你已經安裝了 mod_rails。安裝方式請參考官方網站。
Mac OS X 請額外安裝這支小程式,讓 mod_rails 的設定更為方便。
注意事項:全世界都可以連到你的 Rails Application,即使它是 development !! 建議在程式裡使用 IP 過濾。
—
1: 製作 SSL 憑證
在這裡只考慮「用 Apache 的 OpenSSL 自己簽發 SSL 憑證」的方式,如果你透過管道 ($) 取得 SSL Key 和憑證,那應該可以跳過這步。參考的是 ihower 前輩的這篇文章,不過我把操作寫得詳細一點。
第一個指令:
openssl req -new > server.csr
下圖是產生 server.csr 及 privkey.pem 的流程概要: (按圖可以連到放大的原圖)
需注意:
- 詢問加密字串 (pass phrase) 的時候,會被求輸入 4 個字元以上的字串。這個字串可以亂打,打的時候不會顯示在螢幕上,但同一個字串等等還會用到,所以,打上去之前先做小抄在別的地方,例如記事本之類的。
- Common Name 的地方,其實是要你輸入網域名稱。例如你的 SSL 簽證要用在 www.example.com ,則這裡就要填寫 www.example.com。本文所舉例的設定值都是捏造的。
接下來打入以下兩條指令:
openssl rsa -in privkey.pem -out server.key
openssl x509 -in server.csr -out server.crt \
-req -signkey server.key -days 365
其中當你輸入上列的第一條指令的時候,會要求你輸入剛剛產生 server.crt (及 privkey.pem) 所使用的加密字串 (pass phrase),這時候就從剛剛做小抄的地方複製貼上吧。不過記得這之後要把小抄刪掉。
下圖是以上兩條指令的流程概要: (按圖可以連到放大的原圖)
最後我們就可以得到 server.crt 及 server.key 這兩個檔案。
如果是 Mac OS X Leopard ,則把它們複製到 Apache 設定檔的根目錄 /etc/apache2/ 。
如果是 Ubuntu Linux 8.10,則分別複製到不同的目錄:
sudo cp server.crt /etc/ssl/certs/
sudo cp server.key /etc/ssl/private/
為了安全起見,把這兩個檔案的存取權限設為 400。
—
2: 啟動 Apache 的 SSL 功能
看下去之前先注意這件事: Apache 的 mod_ssl 並不支援多重虛擬主機 (vhost),所以即使你設定了很多個虛擬主機 (多個網域名稱對應到同一個 IP),也只有 1 個 (最先被讀到的那個) 會起作用。詳情請參考這裡。
a) Mac OS X Leopard
Mac OS X Leopard 的方式是在 /etc/apache2/httpd.conf 把這一行前面的註解移除:
Include /private/etc/apache2/extra/httpd-ssl.conf
接著編輯 /etc/apache2/extra/httpd-ssl.conf 修改這兩行,也就是簽證及金鑰的檔案位置,請把它指定到剛剛我們複製到 /etc/apache2 裡面的金鑰檔案:
SSLCertificateFile "/private/etc/apache2/server.crt"
# ...... 隔十幾行
SSLCertificateKeyFile "/private/etc/apache2/server.key"
這裡有個小知識:Mac OS X Leopard 的 /etc 是一個到 /private/etc 的連結,因此 /private/etc 可以視為與 /etc 相同。
接著要讓 Apache 的 mod_vhost 認得 SSL 的 Port。先假設你已經安裝了本文最上面提及的 Passenger 偏好設定面板,那你應該會在 /etc/apache2/httpd.conf 的最下面看到這幾行字,加入 NameVirtualHost *:443 即是:
# Added by the Passenger preference pane # Make sure to include the Passenger configuration (the LoadModule, # PassengerRoot, and PassengerRuby directives) before this section. <IfModule passenger_module> NameVirtualHost *:80 NameVirtualHost *:443 # 加入這一行 Include /private/etc/apache2/passenger_pane_vhosts/*.conf </IfModule>
然後到 Passenger 的偏好設定面板 (系統偏好設定),加入你的 Rails Application 設定:
其中 Folder 是 Rails Application 的根目錄。
如果你的網域並不是 XXXXX.local 的話,例如 www.example.com ,那你還要在 /etc/hosts 加入一行:
127.0.0.1 www.example.com
接著編輯 /etc/apache2/passenger_pane_vhosts/nankang.local.vhost.conf (標紅色字的部份是你的網域名稱):
- 把整個 <
VirtualHost>區段複製一份,貼到它的下方 - 把下面那個區段的
<VirtualHost *:80>改成<VirtualHost *:443> - 加入一行字
RequestHeader set X_FORWARDED_PROTO 'https'
改完大概像這樣:
<VirtualHost *:80>
ServerName nankang.local
DocumentRoot "/Users/chitsaou/src/nankang/public"
RailsEnv development
RailsAllowModRewrite off
<directory "/Users/chitsaou/src/nankang/public">
Order allow,deny
Allow from all
</directory>
</VirtualHost>
# 從上面複製下來,貼到下面,把 80 改成 443
<VirtualHost *:443>
RequestHeader set X_FORWARDED_PROTO 'https' # 加入這行
ServerName nankang.local
DocumentRoot "/Users/chitsaou/src/nankang/public"
RailsEnv development
RailsAllowModRewrite off
<directory "/Users/chitsaou/src/nankang/public">
Order allow,deny
Allow from all
</directory>
</VirtualHost>
最後,透過以下指令重新啟動 Apache
sudo apachectl restart
試試看連線到 https://nankang.local 吧。(或著你自己設的網域名稱)
不過因為是自己簽憑證的,所以會出現「憑證不受信任」是很正常的事。
b) Ubuntu Linux 8.10
先啟動 mod_ssl:
sudo a2enmod ssl
接下來假設你已經用 mod_rails 設定了你的 Rails Application,沒有的話到官方網站抄一份設定檔便是。
編輯 /etc/apache2/sites-available/rails_app (標紅色字的部份是你的設定檔名稱):
- 把整個 <
VirtualHost>區段複製一份,貼到它的下方 - 把下面那個區段的
<VirtualHost *:80>改成<VirtualHost *:443> - 加入一行字
RequestHeader set X_FORWARDED_PROTO 'https' - 在
<VirtualHost *:443>和</VirtualHost>之間加入 SSL 簽證設定:
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt # 憑證的位置
SSLCertificateKeyFile /etc/ssl/private/server.key # 金鑰的位置
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
改完大概像這樣:
<VirtualHost *:80>
ServerName nankang.local
DocumentRoot "/Users/chitsaou/src/nankang/public"
</VirtualHost>
# 從上面複製下來,貼到下面,把 80 改成 443
<VirtualHost *:443>
RequestHeader set X_FORWARDED_PROTO 'https'
ServerName nankang.local
DocumentRoot "/Users/chitsaou/src/nankang/public"
# 加入以下的 SSL 憑證資訊
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
</VirtualHost>
最後,透過以下指令重新啟動 Apache
sudo /etc/init.d/apache2 restart
如果你看到以下的錯誤:
Syntax error on line 6 of /etc/apache2/sites-enabled/rails_app:
Invalid command ‘RequestHeader’, perhaps misspelled or defined by a module not included in the server configuration
那麼只要把 mod_headers 開起來就行了
sudo a2enmod headers
試試看連線到 https://nankang.local 吧。(或著你自己設的網域名稱)
不過因為是自己簽憑證的,所以會出現「憑證不受信任」是很正常的事。
有關 Ubuntu 設定 Apache SSL 及簽發憑證的說明,請閱讀以下這兩個網頁:
—
3: 引入 Controller 的 SSL 支援
這裡先要安裝一個 plugin: ssl_requirement
安裝方法很簡單,在 Rails Project 的根目錄執行:
script/plugins git://github.com/rails/ssl_requirement.git
接著你可以依照 Plugin 網站上的說明,直接在 controllers/application.rb 導入,如此一來在所有的 controllers 都可以用 SSL;或是如果你跟我一樣,只考慮登入的時候需要 SSL,那麼就在相對應的 controllers 導入 SSL 。以一個使用 restful-authentication 為認證機制的網站為例:
更新:後來發現如果僅針對若干 controllers include SslRequirement 的話,會發生某些很悲慘的事。 所以還是一律加在 controllers/application.rb 吧!
## 在 application_controller.rb class ApplicationController < ActionController::Base include SslRequirement # 加入這行 # .... end
4: 決定哪些 actions 需要 SSL
就看官方網站的範例就知道了。
還是以一個有 restful-authentication 的網站為例,至少在開帳號和登入的時候要有 SSL 支援,那便是:
## 在 users_controller.rb class UsersController < ApplicationController ssl_required :new, :create # 加入這行 # ... end ## 在 sessions_controller.rb class SessionsController < ApplicationController ssl_required :new, :create, :destroy # 加入這行 # ... end
這樣就可以了。






[...] 在上述的第二步,你需要輸入一堆資料,我之前寫的這篇文章裡面有一張圖,參考著用。 [...]
[筆記] SSL 憑證購買記 « YORKXIN×YORKXIN
2009 年 二月 23 日 星期一 at 20:09:39
這個和這篇http://www.buildingwebapps.com/articles/6401-using-ssl-in-rails-applications文章好像… @@
ENV
2009 年 十一月 9 日 星期一 at 22:43:39
啊設定方法就這樣而已啊 XD 大家都用 Apache + Passenger + SslRequirement 的組合技,會很像也很正常不是嗎
而且我這篇是完全自己寫的 = = 寫了一個晚上吧
Chitsaou Yorkxin
2009 年 十一月 9 日 星期一 at 22:53:43