5

ハンドラーからいくつかの反復ロジックを引き出し、それをハンドラーごとのミドルウェアに入れたいと考えています。具体的には、CSRF チェック、既存のセッション値 (つまり、認証またはプレビュー ページ) のチェックなどです。

これに関するいくつかの記事を読みましたが、多くの例はサーバーごとのミドルウェア (ラッピング) に焦点を当てていますhttp.Handler: ミドルウェアを必要とする少数のハンドラーのセットがあります。私の他のページのほとんどはそうではありません。したがって、セッションなどのチェックを避けることができれば. それらの要求に適しています。

これまでのところ、私のミドルウェアは通常、次のようになっています。

func checkCSRF(h http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // get the session, check/validate/create the token based on HTTP method, etc.
        // return HTTP 403 on a failed check
        // else invoke the wrapped handler h(w, r)
    }
}

ただし、多くの場合、ラップされたハンドラーに変数を渡したい: テンプレートに渡すために生成された CSRF トークン、またはフォーム データを含む構造体 — ミドルウェアの 1 つは、保存されたフォーム データの存在を事前にセッションにチェックします。ユーザーが URL にヒットする/preview/と、それ以外の場合はリダイレクトされます (プレビューするものが何もないためです!)。

その構造体をラップされたハンドラーに渡して、session.Get/type アサーション/エラー チェック ロジックをミドルウェアに記述しなくても済むようにしたいと思います。

私は次のように書くことができます:

type CSRFHandlerFunc func(w http.ResponseWriter, r *http.Request, t string)

...そして、ミドルウェアを次のように記述します。

func csrfCheck(h CSRFHandlerFunc) http.HandlerFunc {
     return func(w http.ResponseWriter, r *http.Request) {
        // get the session, check/validate/create the/a token based on HTTP method, etc.
        // return HTTP 403 on a failed check
        // else invoke the wrapped handler and pass the token h(w, r, token)
    }

...しかし、それにはいくつかの疑問が生じます:

  • これは、ハンドラーごとのミドルウェアを実装し、リクエストごとの変数を渡す賢明な方法ですか?
  • これをテストする前に (私の開発マシンにアクセスできません!)、ハンドラーを複数のミドルウェアでラップする必要がある場合は、単にr.HandleFunc("/path/preview/", checkCSRF(checkExisting(previewHandler)))? ここで見られる問題は、ミドルウェアが密結合になっていることです。ラップされたミドルウェアは、外側のミドルウェアから変数を受け取って渡す必要があります。これにより、http.HandlerFunc の拡張がトリッキー/複雑になります。
  • ゴリラ/コンテキストは、ここにうまく適合し、2 ~ 3 個のカスタム ハンドラー タイプ (またはジェネリック ハンドラー タイプ) の記述を避けることができますか? もしそうなら、それをどのように利用しますか? または、独自の「コンテキスト」マップを実装できますか (同時アクセスで問題が発生しますか?)。

可能な限り、「ライブラリの作成に巻き込まれないように」という罠にはまらないようにしていますが、ミドルウェアは、プロジェクトの後半で追加/構築する可能性が高いものであり、「それを正しくする」ということです。

これに関するいくつかのガイダンスをいただければ幸いです。これまでのところ、 Go は Web アプリケーションを作成するのに優れていますが、この段階ではまだ多くの例がないため、SO に少し頼っています。

4

1 に答える 1

7

私があなたの質問を正しく理解していれば、追加のパラメーターをミドルウェアに渡す便利な方法を探していますよね?

ここで、これらのパラメーターが何であるかを定義することが重要です。これらは、ミドルウェアの構成値である可能性があります。これらは、Handler タイプの構築時に設定できます)。の代わりにNewMyMiddleware(MyHandler)NewMyMiddleware(MyHandler, "parameter")ここでは問題ありません。

しかし、あなたの場合、CSRFトークンのように、リクエストごとのパラメーターを渡したいようです。Handler[Func]それらをハンドラー関数に渡すと、その署名が変更され、標準インターフェイスから逸脱します。この場合、ミドルウェアがより緊密に結合されていることについては正しいです。

ご自身で解決策について言及されていましたが、私の意見では、コンテキスト マップこのための実行可能なツールです。自分で書くのはそれほど難しいことではありません。基本的に、安全な同時アクセスmap[*http.Request]interface{}のために とが必要です。RWMutexそれでも、単純に使用gorilla/contextするだけで十分です。これは (比較的) 成熟した、優れた API を備えた適切に作成されたパッケージのようです。

恥知らずなプラグイン: CSRF チェックを扱っている場合は、私のnosurfパッケージを試してみませんか?

于 2013-11-05T13:17:26.760 に答える