しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC の RequireHttps 属性は GET 以外の場合には例外を投げるので注意

タイトルの通りですが、ASP.NET MVC を使って SSL が必須のページを実装するのには RequireHttps 属性が便利ですね。しかし、この属性は GET 以外のリクエストが来ると無条件で例外を投げるようになってます。

例えば HEAD リクエストを投げてみると 500 が返ってきます。

f:id:shiba-yan:20141117123133p:plain

実際にコードを見てみると GET 決め打ちのコードとなってます。

// only redirect for GET requests, otherwise the browser might not propagate the verb and request
// body correctly.

if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
    throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
}
ASP.NET MVC / Web API / Web Pages - Source Code

正直なところ、この挙動はいまいちな感じがします。少なくとも例外を投げるのは勘弁してもらいたい。

ヘッダ情報を要求してるのでリダイレクト先を教えるのは問題無いのではないかと思うんですが、新しくこの修正のためだけに属性を作るのも微妙なので、URL Rewrite を使って https へリダイレクトさせます。

<rule name="RequireHttps" enabled="true">
  <match url="(.*)" ignoreCase="false" />
  <conditions>
    <add input="{HTTPS}" pattern="off" />
  </conditions>
  <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>

サーバー変数 HTTPS に on/off が入ってくるので、それを見てリダイレクトするという簡単なルールです。

f:id:shiba-yan:20141117123457p:plain

今度は HEAD リクエストを投げた場合でもリダイレクトになっていることが分かります。こういった処理は URL Rewrite の段階で処理した方がパフォーマンス的にも有利かもしれませんね。