前回にオウム返しBotの最低限の機能を実装しました。
しかし、今の実装ではLINEプラットフォーム外からのアクセスも受け入れてしまう問題があります。
LINEプラットフォームからのアクセスだけ処理するように実装を改善します。
実装方針
署名を検証するのとおり、以下の値が一致することを確認します。
不一致の場合には、処理を中断します。
- HTTPヘッダー
x-line-signature
の値 - ダイジェスト値
- ダイジェスト値 の計算式は以下のとおりです。
Base64(HMAC-SHA256(リクエストボディ、チャネルシークレット))
-
LINE Developersのコンソール画面でチャネルシークレットを入手できます。
- チャネルアクセストークンと同様に、Secret Managerに登録しておきます。
-
HMAC-SHA256の計算には pkg.go.dev/crypto/hmac を使用します。
実装
上の実装方針の通りコーディングするのみです。
func validate(header http.Header, reqBytes []byte) bool {
want := []byte(header.Get("x-line-signature"))
channelSecret := os.Getenv("CHANNEL_SECRET")
mac := hmac.New(sha256.New, []byte(channelSecret))
mac.Write(reqBytes)
got := []byte(base64.StdEncoding.EncodeToString(mac.Sum(nil)))
log.Printf("want HMAC-SHA256 %s", string(want))
log.Printf("got HMAC-SHA256 %s", string(got))
return hmac.Equal(want, got)
}
動作確認
- 正常時のログ例は以下のとおりです。
2023/01/28 01:05:26 want HMAC-SHA256 cdcJyc6cR5lsvYLq9wCtrpzuX/YuchJsNjOk7VZEgJ4=
2023/01/28 01:05:26 got HMAC-SHA256 cdcJyc6cR5lsvYLq9wCtrpzuX/YuchJsNjOk7VZEgJ4=
- LINEプラットフォーム外からCloud Functionsにアクセスするとエラー終了になります。
- チャネルシークレットがわからず、x-line-signatureに正しい値を入れられないため。
2023/01/28 01:01:02 invalid request
ソースコード全体
ソースコード全体は以下のとおりです。
https://github.com/hsmtkk/qiita-gcp-cf-line-bot/blob/main/parrot/parrot.go
次回
以上でオウム返しBotの実装とセキュリティ強化は完了です。
次回はより高度な話題として、セッション管理を扱います。
一問一答完結でなく、複数回のやりとりをおこない、対話的な動作をめざします。