LINE BOT Webhooks の署名検証をC#で実装する
LINE BOT 開発では、ユーザーが送信したメッセージなどのイベントは、指定したURLにHTTPSのPOSTリクエストとして送信されますが、リクエストの送信元が間違いなくLINEからのものであることを確認する必要があります。
LINE API Referenceには以下の様に書かれています。
Signature validation
リクエストの送信元がLINEであることを確認するために署名検証を行わなくてはなりません。 各リクエストには X-Line-Signature ヘッダが付与されています。 X-Line-Signature ヘッダの値と、request body と Channel secret から計算した signature が同じものであることをリクエストごとに 必ず検証してください。
検証は以下の手順で行います。
今回は、これをC#で実装してみましょう。
必要なデータは以下の3つです。
- リクエストのX-Line-Signature ヘッダに格納されている値
- リクエストBODYの値
- Bot アカウントに付与されるChannel Secret(Line DeveloppersのChannels>>Basic Informationで確認できます)
これらを引数にして検証を行う関数を作ります。
using System.Security.Cryptography; using System.Text; public bool VerifySignature(string xLineSignature, string requestBody, string channelSecret) { try { //channnel secret と request body をByte配列に変換する var key = Encoding.UTF8.GetBytes(channelSecret); var body = Encoding.UTF8.GetBytes(requestBody); //channel secretをキーにしてHMAC-SHA256アルゴリズムでrequest bodyのダイジェスト値を得る using (HMACSHA256 hmac = new HMACSHA256(key)) { var hash = hmac.ComputeHash(body, 0, body.Length); //ダイジェスト値をBASE64に変換 var hash64 = Convert.ToBase64String(hash); //X-LINE-Signatureヘッダの値と一致すればOK!! return xLineSignature == hash64; } } catch { return false; } }
これを、Azure Functions(HttpTrigger)で使用する例を以下に示します。
using System.Configuration; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { //Channel Secretの取得。Channel SecretはAzure ポータルでアプリケーション設定に登録しておきます。 var channelSecret = ConfigurationManager.AppSettings["ChannelSecret"]); //Request Body の取得 var contentJson = await req.Content.ReadAsStringAsync(); //X-Line-Signatureヘッダ値の取得 var xLineSignature = req.Headers.GetValues("X-Line-Signature").FirstOrDefault() if (string.IsNullOrEmpty(xLineSignature) || !VerifySignature(xLineSignature, contentJson, channelSecret)) { //検証に失敗 return req.CreateResponse(HttpStatusCode.Forbidden, new { Message = "Signature validation faild." }); } //BOTでやりたい処理... }