2011年1月14日金曜日

WebMatrixの認証設定とヘルパー

WebMatrixを使ってWebPagesの認証機能を利用する場合、WebSecurityヘルパーを使う事になりますね。詳しくは塚田さんがエントリ書いてたのでそちらをどうぞ。

WebMatrix ASP.Net Razorでログイン認証を作る- 1.WebSecurity Helperの概要 « IIS+αでいってみよう

↑ここから何個か続きますね。

基本的にASP.NETの仕組みで認証(Authentication)・承認(Authorization)させてるのでFormsAuthentication周りを知っていることが前提なのかもしれないけど、その辺はヘルパーを使うということでまるっと隠しきろうという感じでしょうね。

WebMatrix入れるとスターターサイトを作れますが、そこにも認証系の機能はひと通り含まれてます。それを参考にするのがいいかなと思うんだけど、1点とても分かりにくいところがある。

それは「ログインページを指定」する方法です。

WebSecurityの規定値は”~/Account/Login”です。これはFormsAuthenticationSettingsクラスにstatic readonlyで宣言されてます。readonlyですよ!変更できないじゃん!

普通にASP.NETの作法通りなら以下の設定をしますよね。
<system.web>
<authentication>
  <forms loginUrl=”…”>

でもWebSecurityはそれを利用しません。さすがカスタム。あと<authorization>設定(承認)は設定すればちゃんと機能します(でも使わないのがWebMatrix流?)。

FormsAuthenticationModule自体は読み込まれてるので、web.configを作成してそれらのセキュションを書いてしまえばよさそうな気がするでしょ?だがしかし!loginUrlは見てくれないんですよ。なぜかというとアプリケーション起動時にFormsAuthenticationの設定をWebMatrix.WebData.ConfigUtilが上書きするからです。

なので、ログインURLを自分で指定したい場合、ソースを追いかけるとわかりますが、以下のようにappSettingsに指定しましょう。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="loginUrl" value="~/Members/LogOn"/>
  </appSettings>
</configuration>

これで、標準のログイン先が変更できます。
なんで、こういう設定が必要かというとHttpのステータスコードを見てFormsAuthenticationModuleがリダイレクトするのがASP.NETのForm認証フローだからです。これを理解してないと自分でSessionやらCookieやらで適当につくろうとしちゃうでしょ?それはとてもよろしくないです。愚行ですよ!

なので、authorizationで認証が必要なパスを指定するか、認証が必要なすべてのページの最初にWebSecurity.RequireAuthenticationUser()を書いておくことです(実際は_PageStartとか_Layoutとかで一括処理ね)。そうするとHttpUnauthorized 401なレスポンスを返そうとするので、FormsAuthenticationModuleがそこに反応してログインページに自動でリダイレクトします。

分かりにくい?

@{  
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "マイ Web サイトへようこそ";
}
<p>
    ASP.NET Web Pages を使用すると、Web 用の優れた .NET ベースのアプリケーションを簡単に作成できます。
</p>
<p>
    <ul>
    @foreach(var moduleName in Context.ApplicationInstance.Modules.AllKeys){
        <li>@moduleName : (@Context.ApplicationInstance.Modules[moduleName].GetType())</li>
    }
    </ul>
    認証済み:@WebSecurity.IsAuthenticated<br/>
    ログインURL:@FormsAuthentication.LoginUrl
</p>


↑こんな感じでdefault.cshtmlに書いておくと読み込まれてるすべてのモジュールと認証状況を表示します。web.configに何も書かない場合、ログインURLには"/Account/Login"と表示されますですよ。

auth1

↑一番下の部分ね。

続いてweb.configファイルをルートに作成し設定してみましょう。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="loginUrl" value="~/Members/LogOn"/>
  </appSettings>
</configuration>

auth2

ちゃんとログインURLが変化してますよね。この状態でログイン必須なChangePasswordページに行ってみる。

auth3

"/Members/LogOn”というページはないので、404エラーになってますが、ちゃんと"/Members/LogOn”にリダイレクトされてるのが確認できます。ぐっじょぶ!
難しい話はこのへんにして、今日のヘルパー。

@helper Show(string message){
        <script type="text/javascript">
            alert('@Html.Raw(message.Replace("'","\\'"))');
        </script>
    }
}
/App_CodeにMessageBox.cshtmlを作成し上記のコードをコピペ。
Default.cshtmlに以下のように書いてみよう。
@{  
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "マイ Web サイトへようこそ";
}
<p>
    ASP.NET Web Pages を使用すると、Web 用の優れた .NET ベースのアプリケーションを簡単に作成できます。
</p>
<p>
    @MessageBox.Show("Hello World! '10")
    @MessageBox.Show("Hello World!")
</p>

あら不思議!サーバーサイドでMessageBox.Showを書いたつもりがクライアントサイドにメッセージボックスが表示されました。デバッガのないWebMatrixならではのちゃらいヘルパーの完成です。

auth4