2018/1/8
第二十天:串接 Line Messaging API Webhook
markdown
大家還記得為什麼我們要作網站嗎?是因為我們要作 Line 聊天機器人啦。因為作 Line 所提供的 Line Messaging API Webhook 是透過 HTTP 協定來完成,所以我們需要弄一台網頁伺服器,讓 Line 有事情時可以透過 HTTP 協定來通知我們。
我們從[第四天:認識 Webhook](https://ithelp.ithome.com.tw/articles/10193212)開始學習怎麼架網頁伺服器,直到[第十九天:發布網站到 Heroku (續)](https://ithelp.ithome.com.tw/articles/10196250),終於成功作出一個能讓別人連線的網頁伺服器。
當然在這個過程中,我們學會的不只是會架網站。我們還學會了怎麼使用檔案總管、小黑框、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 協定](https://ithelp.ithome.com.tw/articles/10195016)有學過的,HTTP status code :`200` 表示成功。也就是說不管誰,傳什麼內容過來,我都會回一個成功。
用 `rails server` 開啟網頁伺服器,試試看直接在瀏覽器輸入網址 [http://localhost:3000/kamigo/webhook](http://localhost:3000/kamigo/webhook):
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyKvCT3iJVXTLqGzWH3jQE0Nj8sfB1Esz1cTS3PwjyaWF7984ypgpBcFhIh0ICd91ecM7TUhJ_KOomFT2NZfwG0ey-ewrRwHWPRMlRXc1c64xOplk8cu2WA70GqP5r3zPYJmLXZc28o94/s1600/3.png)
Rails 返回的結果是 `No route matches [GET] "/kamigo/webhook"`,意思是我們沒有設定 `GET` 連接到 `/kamigo/webhook`,這表示我們直接在瀏覽器網址列輸入網址的話,是不可能產生出一個 `POST` 請求的。
有幾個方法可以作出 `POST` 請求,最常見的 `POST` 請求是在一個網頁上填表單按下送出的時候。我們不會採用這個方案,因為這個方案要寫程式。我們可以使用現成的工具來發出 POST 請求。
# POST 的測試
有一款工具叫作 POSTMAN:[https://www.getpostman.com/](https://www.getpostman.com/)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3O6Lt1aoqaoYBoCydndkjTI3WFdSFwi2fGqTaEi6AGEy-XOYzH1LmGlFfSXLjukTbXJVEU-vAxSgtrLc2VSdVc0rE2Fj_pPxPQpOBIoxZr4GzXALllrkb0OYznwX0E8Y-KcTAcTskUPg/s1600/4.jpg)
點一下 `Windows`。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd1t6KT1Y21-6EOVLnHb-8Op-uM9FfppKBdyF3PLAFN9JNhHqYLJzmTYtujOnz-MYF_Vvgg-NJTOWAU9VjSqRgmQCzTiTEwBCLQz7cMeCUwJfhxAhf46jApBuxPZ4XeTy4CpFaAovfHw/s1600/5.jpg)
選 `x64` 就會開始下載,下載好就點開。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilZn1o5kVlbp1Q-kmuTeqDj92ZECT0_krcVYd_BCUDQHFzUarFnuyVd4HMmMOzWUNAN_QLi6DYaaR2VwWX6RMtGKorTpBx0HkuLUUZk9E4I6qqt34WOrmEUXfGI-HHqOimeQgmTjdaLO0/s1600/6.jpg)
POSTMAN 是一款功能眾多的軟體,但我們用不到進階功能,所以我們就不註冊帳號了,點選下面圈起來的 `Take me straight to the app. I'll create an account another time.` 略過註冊,直接使用。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYcOIV5sakgZLI2-1DuE-fiF2eZ9-9YRN_dIidlK8BaE2wtOXWODr4M83rJKDvP4wqFNBWRileUFVdbhhlec0UYDftIiclS8ZZrGmfB29HxN4d-0VmaCSPZxMu0SmZ5k7tzSH8UHKQOgw/s1600/7.jpg)
這是我們用不到的各種功能,直接關掉即可。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoo5IEmS55g17gFO1qQtDm6XFHORXd_i0zfc3INCcdU_Z-Kb5iB-D4ZpxcLbhAKYC02kNIX-gPLzN5hXXBb8zPkHR_rfRcOG0r-W9ygehD5illS3-utmGXBjJJ39KmYdmbmPzvqrazo0A/s1600/8.jpg)
這個區塊是讓我們填入 HTTP 請求方法和網址的地方。我們要用 `POST` 方法,網址是 `http://localhost:3000/kamigo/webhook`,填好按送出。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNJ6zBAMuI-3DuD0YG65UJAoD4E6N_TBvWyefzQ6aqs__ymrbgriG51GDZZyDA1PHeOmhST7JbGmshZIpXbaTLbk9VLP2XxDv88BMOilfawLMoYpAF_UvWySKng-TvKxlfkcgltqb1CiU/s1600/9.jpg)
結果收到的 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
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP4dXzikFb3w3rNtldyzAPIzekR3JqoZkjMUqdXX-SR2Aez3Ic86MdlbN92mF0HCo1DRrOm4Sg5_RMPPDJvOIbKeV7A0lIXyaOUdQiYSqiMxpMAYrT6kVtsyQWQl1NxUYP9KhXBaQC6SM/s1600/10.jpg)
這是正常的情況,一個人類應該會先開啟一個表單頁,填好表之後再送出。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5hdTVpKghiiL-YK4yCo1t-Cgcx_B7NFKb7cGGjYjP-d7Ens8GHDFKqilIbuppLlvOv1cFoBDabzxOIjRj4xA8jNI5sPRMNo4TQ37Ta6LDNB_prnTBv317GECPiBlRYeqePqgzZyF-vKQ/s1600/11.jpg)
這是被入侵時會發生的情況,壞網頁會讓你的瀏覽器在不經過你同意的情況下,自己發出 `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/](https://developers.line.me/console/):
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR4XX-0afM7EMloUrdMQYnWkLYLSdvpxhlXV-JcVIKH9kIZBj6RA6tp8Ih6g5hWEPlAPmhw0EJcyHFTc9OS7oJxlv02CciBe5rKYCh5Nw1ASNFQN2cU85IbKvJWrHMf0BLJnVa5DcZYgM/s1600/1.jpg)
點聊天機器人進入:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiysddxxB2o1qh_FCsPIsBUV10xO9lJnlSuxsQ_2i5-tARrmxkmOyDES3PF4vXnYwi6onl9wIcYczXSGvEXsHhU5qR3DI0og8bqEBAVg0jlPyVZTfJ0FkbwvhnEYic1aTg2lGM3BvuCyaQ/s1600/12.jpg)
進入頁面後,你要找到上圖所在的 `Messaging settings` 區塊,其中有一項叫作 `Webhook URL`,點一下右邊的筆進入編輯:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggB-6lf6huwfkuQC2xakHwNk5xyhKS9YmVD60NWJ59wg6ZEUtp_ijAsiYlJITtII4aqJjyDBSTHUE66AyNMEMXzdPmCOjU4CEoChXNlNasEGw37LCs2TetA38f-DFG_dayuD7vzw_ym7Q/s1600/13.jpg)
輸入我們剛剛作好的 POST 網址 `people-all-love-kamigo.herokuapp.com/kamigo/webhook`,注意這裡你要填的是你的網站的網址,不要填到我的。還有一個注意事項,開頭的 `https://` 不可以填。
填好後按下 `Update`。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX5f7qOlwnuoxt0MHt1jeUtU-invHKJdgVbxQ36JK99tf0CopAMAZHVvjojkiNcV_DWRMDk4m90MQJPZtTtIQm5FLHZnooaeIq8cHPwyUVee0Ho5lX_44o9YogXSZCdMD7auPf-DbTApo/s1600/14.jpg)
就會在畫面上看到一個 `Verify` 按紐,按下去。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq6UuZPKpPjFTYC9iWb_6nJFcifRkHSw-9mEmfTYXh4ecp6R-KJvANw8jjdc1VTVKeBQGCQK11Yay7jkUR-9J6WdLHD9X4k3pfu_Z7qmNIyTFeE-a2P0MYAU5LsSqPcsKwTzhgQFDFu7Y/s1600/15.jpg)
Success 成功!
今天就先到這,明天就能讓聊天機器人講話了。
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言