「Go のフレームワーク echo でCSRFミドルウェアを使う」シリーズ第2弾です。
ミドルウェアが指定されている場合、基本的には、ハンドラーが実行される前に実行されます。
ですのでたとえば、CSRFミドルウェアによって不正と判断された場合には、URLに割り当てられたハンドラー処理をスキップし、ルーターから直接、クライアントへ結果が返却されることになります。
しかしこの場合に、具体的にどのような結果が返るのか、ということはリファレンスには記載されていません。
ということで今回もソースを追っていきましょう。
…と言っても、今回は非常に単純な話で終わってしまうのですが…。
該当のソースはここです。
https://github.com/labstack/echo/blob/master/middleware/csrf.go#L142
ここで書かれているのはつまり:
送信されたトークンが不正であった場合 -> http.StatusBadRequest(=400)
トークンが一致しなかった場合 -> http.StatusForbidden(=403)
というように、HTTPレスポンスヘッダがセットされるということですね。
さて、これをルーター内でキャッチするには、e.HTTPErrorHandlerを使用することになります。
例えば次のような形になりますね。
e := echo.New()
e.Use(middleware.CSRF())
e.POST(“/foobar”, handler_foobar)
e.HTTPErrorHandler = func(err error, c echo.Context) {
if h, ok := err.(*echo.HTTPError); ok {
switch h.Code {
case http.StatusBadRequest:
// 400
case http.StatusForbidden:
// 403
default:
// その他
}
}
}
もし、BadRequestやForbiddenが他のミドルウェアなどでも発生しうる場合、BadRequestである場合は別として、もし「(開発中の確認作業として)ForbiddenがCSRFミドルウェア由来のものであるか否かを確認したい」という状況はありえるかもしれません。
その場合、err.Error()の中身にはInvalid csrf token文字列が入りますので、ログに出せば確認可能かと思います。
これをクライアント側で確認できるようにしたいと考えた場合、エラーメッセージそのものを条件判別に使うのは危険(echoのバージョンアップでメッセージが変わることは十分ありうる)と思いますので、開発用のHTTPヘッダにerr.Error()の中身を載せて返す、などという方が妥当であるものと思います。