WebSurfer's Home

Filter by APML

ASP.NET Web アプリ開発用サーバー証明書の更新

by WebSurfer 4. April 2025 13:00

Visual Studio Community 2022 Version 17.13.5 で ASP.NET Web アプリを IIS Express 上で動かそうとしたら、開発用のサーバー証明書が期限切れとなっていたので更新したのですが、一筋縄ではいかなかったので、その時の顛末を書いておきます。

開発用のサーバー証明書

上の画像の通り、開発用のサーバー証明書には 2 種類あって、フレンドリ名 IIS Express Development Certificate が IIS Express 用、ASP.NET Core HTTPS development certificate が Kestrel 用です。いずれも自己署名証明書で、Visual Studio で作業を行う際に生成されます。

ちなみに上の画像の証明書は今日 2025/4/4 に新規作成したもので、有効期限は作成日から IIS Express Development Certificate が 5 年、ASP.NET Core HTTPS development certificate が 1 年となっています。

有効期限が切れたら Visual Studio が自動的に更新してくれると思っていたのですが、少なくとも Visual Studio Community 2022 Version 17.13.5 ではそうではなかったということで、どのように対応したかをこのブログに備忘録として書いておくことにした次第です。

古い証明書が残ったままではダメなのかと思って、上の画像の管理コンソールの「信頼されたルート証明書」の「証明書」にある期限切れの IIS Express Development Certificate を削除してから Visual Studio 2022 で ASP.NET Web アプリを起動して IIS Express で動かしてみました。しかしながら、新しい証明書が発行されることはなかったです。さらに、古い証明書は削除済みにもかかわらず、ブラウザ上にはそれを使っているという警告が出ます。Visual Studio 2022 を再起動してから試してみたのですが同じでした。

2025/4/10 追記: 今頃気づいたのですが、期限切れの証明書は削除したのにブラウザ上にはそれを使っているという警告が出るのは、どこかで証明書情報がキャッシュされているからという可能性が高そうです。管理コンソールで期限切れの証明書を削除した後、まずはブラウザのキャッシュの削除と「SSL 状態のクリア(S)」(下の画像参照) を行うべきだったかもしれません。

SSL 状態のクリア

Visual Studio 2022 の不具合かと思って、Visual Studio Community 2019 Version 16.11.45 を起動して試してみました。すると、Microsoft のチュートリアルの「アプリを実行する」のセクションにあるダイアログ(下の画像参照)が出てきたので[Yes]ボタンをクリックして証明書を作成、

確認ダイアログ

Security Warning

・・・できたと思ったのですが、状況は変わらなかったです。

Visual Studio 2022 で ASP.NET Web アプリを起動して IIS Eaxpress で動かしてみると、依然として、ブラウザ上には管理コンソールで削除した期限切れの証明書を使っているという警告が出ます。Visual Studio 2019 と 2015 でも試してみましたが状況は同じでした。管理コンソールで「信頼されたルート証明書」の「証明書」の中身を見ると、削除した期限切れの証明書は存在しませんし、上の Visual Studio 2019 の操作で発行されたと思った新しい証明書もありませんでした。

ググってヒットしたネットの記事を見ると C:\Program Files (x86)\IIS Express フォルダにある IisExpressAdminCmd.exe コマンドを使って対応するという記事を目にしました。調べてみましたがそのコマンドの Microsoft のドキュメントは見つかりませんでしたので、実行結果がどうなるのか詳しいことが分かりません。

そういう訳の分からないコマンドを実行する勇気は自分にはありませんでしたので、さらにググって調べてみると、stackoverflow の記事 How do I restore a missing IIS Express SSL Certificate? の回答に IIS Express を修復して解決したとありましたので試してみました。(回答に "I typically run appwiz.cpl to launch the old control panel applet and run repair from there." とありますが、appwiz.cpl を起動するのは自分の Windows 10 では「コントロールパネル」から「プログラムと機能」を立ち上げたのと同じです)

IIS Express の修復

その後で ASP.NET Web アプリを Visual Studio 2022 から IIS Express 上で実行してみました。やはり、ブラウザ上には証明書が期限切れという警告が出ました。しかしながら、ブラウザに表示された証明書の有効期限は、当初のホントに期限切れとなっていた証明書の日付とは異なり、たぶん Visual Studio 2019 で作業した時に再生されたと思われる新証明書の有効期限 2030/04/04 となっていました。なぜ、ブラウザは有効期限が 2030/04/04 と 5 年も先と認識しているのに、期限切れという警告を出したのか謎です。

Visual Studio 2022 を再起動して試してみると、今度はブラウザ上では警告なしで目的のページが表示されました。管理コンソールで「信頼されたルート証明書」の「証明書」の中身を見ると、この記事の一番上の画像の通り有効期限が 2030/04/04 の IIS Express Development Certificate が含まれていました。

IIS Express Development Certificate は IIS Express が発行するとのことですが、IIS Express に証明書を発行させて所定の証明書ストアに配置し警告を出さずに動くようにするのは Visual Studio の仕事のようです。何故かその連携がうまく行ってなかったのが、IIS Express の修復で解決できたのでしょうか?

一体どうなっているのかは自分には分かりません。これ以上深く追求する気力はありませんので、次回同様な IIS Express Development Certificate 期限切れ問題が出たら、上に書いたことを参考に解決に当たりたいと思っています。


ちなみにですが、Visual Studio 2022 のテンプレートを使って ASP.NET Core アプリのプロジェクトを作成すると、現在のところデフォルトでは Kestrel 上で動くように設定されています。

アプリを IIS Express 上で動かすには下の画像のように Visual Studio のドロップダウンメニューで IIS Express を選びます。

Web サーバーの選択

それにより、IIS Express を使ったインプロセスホスティングモデルで動くようになります。

IIS Express の設定


もう一つ、Kestrel 用の証明書 ASP.NET Core HTTPS development certificate の更新については、たぶん Visual Studio が自動的にやってくれると思いますが、もし自動更新がされない場合は、先の記事「dotnet dev-certs https コマンドについて」に書いたとおり、dev-certs https コマンドを実行して更新できます。

先の記事の手順、(2) dotnet dev-certs https --clean 実行、(4) dotnet dev-certs https 実行、(6) dotnet dev-certs https --trust 実行で新規作成したのがこの記事に一番上の画像にある ASP.NET Core HTTPS development certificate です。

Tags: , , ,

DevelopmentTools

dotnet dev-certs https コマンドについて

by WebSurfer 30. March 2023 21:43

dotnet dev-certs https コマンドについて調べたことを備忘録として残しておきます。

dotnet dev-certs コマンド

dotnet dev-certs コマンドは、Microsoft のドキュメント dotnet dev-certs に書いてありますように、開発用のサーバー証明書の作成・管理を行うためのツールです。

具体的には、フレンドリ名が ASP.NET Core HTTPS development certificate という自己署名証明書を作成・管理するツールです。その証明書を使って、ASP.NET Core Web アプリの開発中に、Web サーバーの Kestrel がブラウザなどのクライアントと HTTPS 通信ができるようになります。

(注: IIS Express でホストする場合は IIS Express Development Certificate というフレンドリ名の証明書が使用されます。このスレッドの話は関係ないので注意してください。)

このコマンドの実行によって証明書マネージャーに表示される証明書がどのようになるか、証明書がないときアプリを Kestrel で動かそうとするとどうなるかも以下に合わせて書いておきます。

(1) 初期状態

Visual Studio を開発に使っていれば自力で dotnet dev-certs コマンドを打って証明書を作る必要はなく、Visual Studio がコマンドを使って必要な証明書を生成してくれます。下の証明書マネージャーの画像がその結果で、発行先が localhost となっているのが開発用サーバー証明書です。

開発用サーバー証明書

有効期限切れのものが含まれていますが (何年か Visual Studio で作業しているうちに追加されたものです)、作業していて支障はなかったのでそのままにしていました。

この中のフレンドリ名 ASP.NET Core HTTPS development certificate という証明書をすべて削除してから、新しく証明書を作成し、開発環境でそれを使って HTTPS 通信ができるようにします。

(2) dotnet dev-certs https --clean 実行

既存の証明書を削除するためコマンドラインから dotnet dev-certs https --clean を実行します。

コマンドを打つと下の画像の「ルート証明書ストア」というダイアログが出て削除してよいかが確認されるので[はい]をクリックします。(上の画像のように複数証明書がある場合は複数回ダイアログが出ます)

「ルート証明書ストア」ダイアログ

削除に成功するとコマンドラインに "HTTPS development certificates successfully removed from the machine." と表示され、証明書マネージャーの[個人]>[証明書]および[信頼されたルート証明書]>[証明書]にあったフレンドリ名 ASP.NET Core HTTPS development certificate の証明書はすべて削除されます。

(IIS Express 用の証明書 IIS Express Development Certificate にはこのコマンドは影響ありません)

この状態でコマンドラインから dotnet dev-certs https --check を実行すると "No valid certificate found." と表示されます。

(3) アプリの実行

証明書を削除した後、Visual Studio 2022 で Kestrel を使って ASP.NET Core Web アプリを実行すると「ASP.NET Core SSL 証明書を信頼する」というダイアログが出ます。

ASP.NET Core SSL 証明書を信頼する

[いいえ]を選択すると下の画像のダイアログが出て「Web サーバー 'MvcCore6App2' に接続できません。Web サーバーはもう実行されてません」というメッセージが表示されて終わってしまいます。

ダイアログ

コンソールを見ると以下の例外が出ていました。

Unhandled exception. System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.

(IIS Express 用の証明書 IIS Express Development Certificate には影響はありませんので、Visual Studio 2022 の設定を IIS Express を使うようにしてアプリを実行すれば上のような問題はありません)

(4) dotnet dev-certs https 実行

証明書を作成するためコマンドラインから dotnet dev-certs https を実行します。作成に成功すると "The HTTPS developer certificate was generated successfully." というメッセージが表示されます。

証明書マネージャーを見ると[個人]>[証明書]にフレンドリ名 ASP.NET Core HTTPS development certificate という証明書が追加されています。

証明書マネージャー

ただし、この時点では[信頼されたルート証明書]>[証明書]には ASP.NET Core HTTPS development certificate は存在しません。

この状態で上の (3) と同様にアプリを実行してみます。同じく「ASP.NET Core SSL 証明書を信頼する」というダイアログが出るので[いいえ]を選択すると、今度は InvalidOperationException 例外はスローされず、自己署名証明書を使った場合の警告がブラウザに表示されます。

プライバシーエラー

警告を無視して進めればブラウザにコンテンツの表示はできます。

(5) dotnet dev-certs https --check 実行

コマンドラインから dotnet dev-certs https --trust を実行しても証明書が発行されたかどうかを確認できます。発行されていると以下のようなメッセージが返ってきます。

A valid certificate was found: 8216607E62A7221B7EFEC3022C8AD599DC1728B1 - CN=localhost - Valid from 2023-03-28 13:07:39Z to 2024-03-27 13:07:39Z - IsHttpsDevelopmentCertificate: true - IsExportable: true
Run the command with both --check and --trust options to ensure that the certificate is not only valid but also trusted.

このコマンドは証明書の情報を確認するためだけのものです。証明書を作成することもなく、作成済みの証明書には何も影響しません。

(6) dotnet dev-certs https --trust 実行

上の (4) で発行した証明書を「信頼されたルート証明書」として登録するため、コマンドラインから dotnet dev-certs https --trust を実行します。

コマンドを入力すると、コマンドラインには "Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not previously trusted. Click yes on the prompt to trust the certificate." というメッセージが表示され、下の画像のセキュリティ警告ダイアログが表示されます。

セキュリティ警告ダイアログ

[はい]をクリックして処理を継続します。成功するとコマンドラインには "Successfully trusted the existing HTTPS certificate." というメッセージが表示されます。

証明書マネージャーを見ると[信頼されたルート証明書]>[証明書]に ASP.NET Core HTTPS development certificate が追加されています。

証明書マネージャー

この後で Visual Studio からアプリを実行すれば証明書の問題はなくなり HTTPS 通信を使っての開発ができるようになります。

Tags: , , , ,

CORE

要求の中断による処理のキャンセル (CORE)

by WebSurfer 11. July 2021 13:07

IIS を使ってのインプロセス ホスティング モデル(この記事の下の方の図参照)でホストされる ASP.NET Core Web アプリは、クライアントによる要求の中断を検出してサーバー側の処理をキャンセルすることができます。(.NET Framework 版の ASP.NET の場合は別の記事「要求の中断による処理のキャンセル (MVC5)」を見てください)

要求の中断

クライアントによる要求の中断とは、上の画像の赤丸印の中のブラウザの ✕ ボタンをクリックするとか Esc キーを押す、Ajax を使っての要求の場合は XMLHttpRequest.abort() メソッドを実行することを意味します。

処理のキャンセルには HttpContext.RequestAborted プロパティで取得できる CancellationToken を利用します。クライアントが上に書いた要求の中断操作を行うと、取得した CancellationToken は操作を取り消す通知を配信します。

キャンセル処理は基本的に先の記事「非同期タスクのキャンセル」に書いたことと同様で、以下のようになると思います。

  1. HttpContext.RequestAborted プロパティで CancellationToken を取得しキャンセルをリッスンするタスクに渡す。(CancellationToken の取得先の CancellationTokenSource の初期化等は ASP.NET Core フレームワークがやってくれるようです)  
  2. タスクにはキャンセルをリッスンして適切に処置を行うコードを実装しておく。
  3. クライアントによる要求の中断が検出されると、フレームワークは CancellationTokenSource.Cancel メソッドを呼び出し、CancellationToken を通じてリッスンしているタスクにキャンセルを通知する。
  4. キャンセル通知を受けたタスクは、あらかじめ実装されているコードに従ってキャンセル処置を行う。  

CancellationToken を渡す方法ですが、ネットで見つけた記事 Handling aborted requests in ASP.NET Core に書いてある通り、渡し先のタスクが MVC や Web API のアクションメソッドであれば引数に CancellationToken を追加しておけば、それに HttpContext.RequestAborted から取得した CancellationToken をモデルバインドしてくれます。

検証は Visual Studio 2019 を使って、以下のコードを [デバッグ(D)] ⇒ [デバッグの開始(S)] で IIS 10 Express のインプロセスホスティングで実行して行いました。検証に使用したブラウザは Edge v91.0.864.67, Chrome v91.0.4472.124, Firefox v89.0.2, IE11, Opera v77.0.4054.203 で、いずれもこの記事を書いた時点での最新版です。

View

@{
    ViewData["Title"] = "Cancel";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Cancel</h1>

<input type="button" id="ajaxRequest" value="Ajax Request" />
<br />
<input type="button" id="abortButton" value="Abort" />
<br />
<div id="result"></div>

@section Scripts {
    <script type="text/javascript">
        //<![CDATA[

        var xhr;

        $(function () {
            $('#ajaxRequest').on('click', function (e) {
                xhr = $.ajax({
                    url: '/home/cancel',
                    method: 'get',
                }).done(function (response) {
                    $("#result").empty;
                    $("#result").text(response);
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    $("#result").empty;
                    $("#result").text('textStatus: ' + textStatus +
                        ', errorThrown: ' + errorThrown);
                });
            });

            $('#abortButton').on('click', function (e) {
                if (xhr) {
                    xhr.abort();
                }
            });
        });
        //]]>
    </script>
}

Controller / Action Method

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MvcCore5App4.Models;
using System.Diagnostics;
using Microsoft.AspNetCore.Authorization;
using System.Threading;
using System.Threading.Tasks;
using System;
using Microsoft.AspNetCore.Identity;
using MvcCore5App4.Data;

namespace MvcCore5App4.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        // ・・・中略・・・

        public async Task<IActionResult> Cancel(CancellationToken token)
        {
            _logger.LogInformation($"start: {DateTime.Now:ss.fff}");
            await Task.Delay(5000, token);
            _logger.LogInformation($"end: {DateTime.Now:ss.fff}");
            return View();
        }
    }
}

上のコードの Task.Delay(5000, token) では渡した token を Deley メソッドの中で継続的に観察しているようで、このメソッドが実行が開始された後でもそれから 5 秒以内ならブラウザで要求を中断すると TaskCanceledException がスローされて処理が終わります。

下の Visual Studio 2022 の「出力 (Output)」画像を見てください。Visual Studio 2022 でデバッグ実行すると上のコードの _logger.LogInformation メソッド出力が表示されます。

Visual Studio 2022 の「出力 (Output)」

赤文字の Start - Complete はブラウザからアクションメソッドを呼び出してから何もしないで 5 秒待って処理を完了させた結果、Start again - Cancelled はアクションメソッドを呼び出して 5 秒以内にブラウザで要求を中断した結果です。

Entity Framework を使ってデータベースにアクセスして処置を行うときに使う ToListAsync とか SaveChangesAsync などや、HttpClient の SendAsync とか PostAsync なども同様かというのが問題と思いますが、詳しくは調べてなくて分かりません。

ToListAsync(token) メソッドで少し調べてみた限りでは、ToListAsync(token) の次の行で CancellationTokenSource.Cancel() としても完了してしまいました。Task.Delay(5000, token) と違って即終わってしまうので間に合わないのか、走り出したらキャンセルは効かないということなのかは分かりません。

ホスティングモデルによる違いですが、Visual Studio 2019 で IIS 10 Express を使ってのアウトプロセス ホスティング モデルでは要求の中断による処理のキャンセルはできませんでした。

Microsoft のドキュメント「インプロセスおよびアウトプロセス ホスティングの相違点」にインプロセス ホスティングでは "クライアントの切断が検出されます。 クライアントが切断されると、HttpContext.RequestAborted キャンセル トークンが取り消されます" と書いてあります。裏を返すとアウトプロセスホスティングではダメと言っているようです。

構成の違いは以下の図(Microsoft のドキュメントから借用)の通りですが、IIS では切断は検出されるものの Kestrel との間は HTTP 通信なので Kestrel に切断を伝えるすべがないということではないかと思います。ちなみに IIS をリバースプロキシとして使わず Kestrel をエッジサーバーとした場合はインプロセスホスティングと同様に切断は検出されキャンセルも効きます。

インプロセス ホスティング

インプロセス ホスティング モデル

アウトプロセス ホスティング

アウトプロセス ホスティング モデル

Linux 系の OS の場合は Nginx とか Apache をリバースプロキシに使って Kestrel で ASP.NET Core アプリをホストする構成(IIS を使ってのアウトプロセスホスティングと同じ)になるので、この記事に書いてある手段ではキャンセルはできないということになります。

Tags: , , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。ブログ2はそれ以外の日々の出来事などのトピックスになっています。

Calendar

<<  April 2025  >>
MoTuWeThFrSaSu
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar