Go のフレームワーク echo でCSRFミドルウェアを使う(2)結果を取り出す


「Go のフレームワーク echo でCSRFミドルウェアを使う」シリーズ第2弾です。

ミドルウェアが指定されている場合、基本的には、ハンドラーが実行される前に実行されます。 ですのでたとえば、CSRFミドルウェアによって不正と判断された場合には、URLに割り当てられたハンドラー処理をスキップし、ルーターから直接、クライアントへ結果が返却されることになります。

しかしこの場合に、具体的にどのような結果が返るのか、ということはリファレンスには記載されていません。 ということで今回もソースを追っていきましょう。

…と言っても、今回は非常に単純な話で終わってしまうのですが…。

該当のソースはここです。 https://github.com/labstack/echo/blob/master/middleware/csrf.go#L142

ここで書かれているのはつまり:

  1. 送信されたトークンが不正であった場合 -> http.StatusBadRequest(=400)

  2. トークンが一致しなかった場合 -> 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()の中身を載せて返す、などという方が妥当であるものと思います。

最新記事

すべて表示

SQLite(sqlite3)で “no such table”

小ネタです。 SQLiteを使っていて "no such table" とエラーが出た場合、 DBファイル名の指定が空になっている、という凡ミスを起こしていないかを確認してみましょう。 ・・・ そういう凡ミスをしてしばし悩んだので… ファイル名の指定が空になっている場合、一時的なインメモリDBとして保存されます(※1)。 つまりDB接続を切断すると中身は消えます。 なので接続

アプリケーションサーバにポートを指定せずに起動すると?

最近、 Goで書かれたアプリケーションサーバが起動しない! ->原因: .env ファイルが欠けていた というドタバタがありました。 結局Goと関係ないですが、この時、 「あまりGoに慣れてないのでGoの問題かと…」「DockerまだよくわかってなくてDockerの問題かと…」 というような声があったのて、あえてGoで検証してみようと思ったわけです。 さて、Goでサーバサイドのシステムを作

GitLab 9.1.2 (MySQL) を 11.4.0 (PostgreSQL) にアップグレード

弊社ではかなり前からGitLab(CE)を自社環境で運用しているのですが、ふと気付くと、バージョンがだいぶ先に行ってしまっていました。 とくに最近のバージョンでは Auto DevOps なども使えるようになっていたりするので、さすがにそろそろキャッチアップしたいと考えたわけです。 現行の環境は次の通りです: GitLab 9.1.2 sameersbn/gitlab 使用 MySQL 5.6