2018/1/8

第二十天:串接 Line Messaging API Webhook

大家還記得為什麼我們要作網站嗎?是因為我們要作 Line 聊天機器人啦。因為作 Line 所提供的 Line Messaging API Webhook 是透過 HTTP 協定來完成,所以我們需要弄一台網頁伺服器,讓 Line 有事情時可以透過 HTTP 協定來通知我們。

我們從第四天:認識 Webhook開始學習怎麼架網頁伺服器,直到第十九天:發布網站到 Heroku (續),終於成功作出一個能讓別人連線的網頁伺服器。

當然在這個過程中,我們學會的不只是會架網站。我們還學會了怎麼使用檔案總管、小黑框、Sublime Text、git 和 heroku。這中間並沒有浪費時間,因為所有的學習都會在這個時候用上。而你終於有能力可以開始來接 Line Messaging API 啦。

接下來的文章會採取一邊實作,一邊說明的方式。同時也會一邊複習之前學過的東西。而今天我們的目標是完成 Line Messaging API Webhook 的串接。

接收第一個 POST 請求

因為 Line 會傳東西給我們,所以 HTTP 請求方法會是 POST,不會是以往我們使用的 GET,我們先作一個能接受 POST 的網址出來:

config/routes.rb 加入一行:

  post '/kamigo/webhook', to: 'kamigo#webhook'

app/controllers/kamigo_controller.rb 加入以下函數:

  def webhook
    head :ok
  end 

head :ok 的意思是傳回 HTTP status code :200 以及空的 HTTP body。複習一下在第十二天:從瀏覽器認識 HTTP 協定有學過的,HTTP status code :200 表示成功。也就是說不管誰,傳什麼內容過來,我都會回一個成功。

rails server 開啟網頁伺服器,試試看直接在瀏覽器輸入網址 http://localhost:3000/kamigo/webhook

Rails 返回的結果是 No route matches [GET] "/kamigo/webhook",意思是我們沒有設定 GET 連接到 /kamigo/webhook,這表示我們直接在瀏覽器網址列輸入網址的話,是不可能產生出一個 POST 請求的。

有幾個方法可以作出 POST 請求,最常見的 POST 請求是在一個網頁上填表單按下送出的時候。我們不會採用這個方案,因為這個方案要寫程式。我們可以使用現成的工具來發出 POST 請求。

POST 的測試

有一款工具叫作 POSTMAN:https://www.getpostman.com/

點一下 Windows

x64 就會開始下載,下載好就點開。

POSTMAN 是一款功能眾多的軟體,但我們用不到進階功能,所以我們就不註冊帳號了,點選下面圈起來的 Take me straight to the app. I'll create an account another time. 略過註冊,直接使用。

這是我們用不到的各種功能,直接關掉即可。

這個區塊是讓我們填入 HTTP 請求方法和網址的地方。我們要用 POST 方法,網址是 http://localhost:3000/kamigo/webhook,填好按送出。

結果收到的 status code 是 422,這是怎麼回事呢?

檢查一下 rails server 的小黑框會看到:

Started POST "/kamigo/webhook" for 127.0.0.1 at 2018-01-08 01:55:37 +0800
Processing by KamigoController#webhook as */*
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 2ms



ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

...下略

為了防止世界被破壞,為了守護世界的和平...這是為了防範一種叫作 CSRF 的入侵手法。大概解釋一下他的原理:我可以作一個網頁,讓你在開啟網頁時,就讓你的瀏覽器對另一個網站發出 POST 請求,因為是從你的瀏覽器發出的,所以另一個網站如果沒有作檢查,可能就會中招。CSRF 可以代替你做很多事,比方說如果 Line 沒有防的話,我就可以讓你買 Line 貼圖送給我。

圖解 CSRF

這是正常的情況,一個人類應該會先開啟一個表單頁,填好表之後再送出。

這是被入侵時會發生的情況,壞網頁會讓你的瀏覽器在不經過你同意的情況下,自己發出 POST 請求給另一個網站。

CSRF 的防治

為了防止這個情形,我們的 Rails 網站會在人類在發出 GET 請求開啟表單頁時,就先給你一個號碼牌(CSRF token),只有帶著正確號碼的號碼牌的人才能進 POST 請求,要不然就會被門口的警衛擋下來。但因為 Line 只會直接對我們發 POST,所以我們不能使用表單號碼牌的機制,我們會使用的是 Line 給我們的 Channel access token,這部分之後會再說明。

關閉 CSRF 的檢查

我們不能透過 Rails 內建的檢查機制來防治 CSRF,所以我們得先關閉內建的 CSRF 檢查。

app/controllers/kamigo_controller.rb 中加入一行:

protect_from_forgery with: :null_session

通常這行會放在最上面,像這樣:

class KamigoController < ApplicationController
  protect_from_forgery with: :null_session
  ...下略

弄好後存檔,此時再去按 POSTMAN 的 Send,就會得到 Status: 200 OK,而我們的小黑框顯示的變成這樣:

Started POST "/kamigo/webhook" for 127.0.0.1 at 2018-01-08 02:41:37 +0800
Processing by KamigoController#webhook as */*
Can't verify CSRF token authenticity.
Completed 200 OK in 3ms

其中的 Can't verify CSRF token authenticity. 是在講說他沒有完成 CSRF 檢查。

上傳程式碼

我們上傳程式碼,上傳程式碼的三步驟:

git add .
git commit -m "新增 webhook"
git push heroku master

應該是會成功啦,我就不貼訊息了。

串接 Line Messaging API Webhook

開啟 Line developer 後台 https://developers.line.me/console/

點聊天機器人進入:

進入頁面後,你要找到上圖所在的 Messaging settings 區塊,其中有一項叫作 Webhook URL,點一下右邊的筆進入編輯:

輸入我們剛剛作好的 POST 網址 people-all-love-kamigo.herokuapp.com/kamigo/webhook,注意這裡你要填的是你的網站的網址,不要填到我的。還有一個注意事項,開頭的 https:// 不可以填。

填好後按下 Update

就會在畫面上看到一個 Verify 按紐,按下去。

Success 成功!

今天就先到這,明天就能讓聊天機器人講話了。

沒有留言: