WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

Web Forms アプリの Email Confirmation

by WebSurfer 2020年8月10日 14:05

ASP.NET Web Forms アプリで登録・パスワード再取得のためのメール送信機能を利用する場合、テンプレートで実装されたコードを使うとメール本文に含まれる確認先の URL にアプリケーション名が含まれないという注意事項を書きます。(結果、メール本文に張られたリンクの URL が正しくないのでクリックしても確認できません)

アプリケーション名が含まれない

.NET Framework 版の ASP.NET Web Forms の Web アプリケーションプロジェクトを Visual Studio 2019 のテンプレートを使って、ユーザー認証に「個別のユーザーアカウント」(ASP.NET Identity) を選んで作った場合の話です。ASP.NET MVC5 ではこの問題はありません。

元の話は Teratail のスレッド「リセット画面のURLをアプリケーションルートにしたい」のものです。そのスレッドを見て初めてそういう問題があることを知りました。

メール本文に含めて送信する確認先の URL は、Models/IdentityModels.cs に含まれるヘルパーメソッド GetUserConfirmationRedirectUrl と GetResetPasswordRedirectUrl で Uri(Uri, String) コンストラクタを使って取得しています。

Uri(Uri, String) コンストラクタの第 1 引数に HttpRequest.Url プロパティで取得する Uri を、第 2 引数に "/Account/..." から始まる相対 URL の文字列を設定して Uri オブジェクトを作り、それから AbsoluteUri プロパティを使って絶対 URL を取得して確認メールの本文に張り付けています。

この記事の一番上のデバッグ画像を見てください。問題のヘルパーメソッド GetUserConfirmationRedirectUrl, GetResetPasswordRedirectUrl ではないですが、簡単に問題を再現するために Page_Load メソッドに同等のコードを書いて検証してみました。

なお、Visual Studio (IIS Express) では以下のように Request.Uri にアプリケーション名 myapp が含まれるよう[プロジェクトの URL (J)]を設定しています。

アプリケーション名 myapp を設定

上のデバッグ画像のとおり、ローカル変数の rquestUri にはアプリケーション名 myapp を含めた Uri オブジェクトを取得できています。ローカル変数 callbackUrl が確認先の URL になりますが、アプリケーション名 myapp は含まれません。これが問題です。

ちなみに、ASP.NET MVC アプリでは Url.Action を使ってアプリケーション名を含めた絶対 URL を取得していますのでこういう問題はないです。

対処方法として、ヘルパーメソッド GetUserConfirmationRedirectUrl と GetResetPasswordRedirectUrl 内にアプリケーション名をハードコーディングするのは好ましくはなさそうです。アプリケーション名の変更、アプリの移植で問題となりますので。

ルート演算子 (~) と VirtualPathUtility.ToAbsolute メソッドを利用して "~" に相当するパスを取得するのがよさそうです。具体例は以下の画像を見てください。

VirtualPathUtility.ToAbsolute メソッド利用

この記事の例のように、アプリケーション名が myapp の場合、VirtualPathUtility.ToAbsolute メソッドの引数に "~" を設定すると戻り値は "/myapp" になります。引数に "~/Account/ResetPassword" を設定すると(文字列先頭に "~" を付与している点に注意)戻り値は "/myapp/Account/ResetPassword" となります。以下の画像を見てください。

このようにすればアプリケーション名をハードコーディングしなくて済みます。


その他のパス設定の問題

テンプレートで生成されたコードのパス設定の問題は他にもあって、例えば Account/Manage.aspx ページでも以下のようにリンク先の URL にルート演算子 (~) が設定されてないです。

URL にルート演算子 (~) が設定されてない

リンクをクリックしても、普通はパスが通らないので、404 Not Found エラーとなってすぐ気が付くと思うかもしれませんが、開発環境ですと訳が分からないサーバーエラーになることがあるかもしれません。

実は、上の画像にあるように Visual Studio で[プロジェクトの URL (J)]を設定したのですが、その際 IIS Express 用の applicationHost.config 設定で application path="/" と application path="/myapp" が両方有効になって、/Account/ManagePassword.aspx に遷移できてしまったのです。

認証チケットは /mayapp/Acount/Login.aspx で取得しているのですが、/Account/ManagePassword.aspx では認証されないので User.Identity.GetUserId() でユーザー ID を取得できず訳が分からないサーバーエラーになりました。

これには半日ぐらい悩まされました。どうも Microsoft としては Web Forms アプリには力が入ってなくて、テンプレートで生成されるコードでも 100% 信頼できないような感じがします。

Tags: , ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2020年8月  >>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar