C# Tips | 文字列処理:HTMLアンエスケープ

C# C#
スポンサーリンク

はじめに 「HTMLアンエスケープ」は“記号に戻して、元のテキストを取り出す”技

さっきの「HTMLエスケープ」は、
<>&lt;&gt; に変えて「安全な文字列」にする処理でした。

HTMLアンエスケープは、その逆です。

&lt;b&gt;太郎&lt;/b&gt;
"<b>太郎</b>" に戻す処理。

「画面に出すためにエスケープしたもの」や
「外部システムからエスケープ済みで渡されたもの」を、
“人間が読む元の形”に戻したいときに使います。

ここでは、初心者向けに、

  • HTMLアンエスケープの役割
  • C#での基本API(HtmlDecode)
  • 具体的な変換例
  • エスケープとの組み合わせ方・注意点
  • 業務ユーティリティとしてのまとめ方

を、例題付きでかみ砕いて説明していきます。


HTMLアンエスケープの役割をイメージする

「エンティティ」を“ふつうの文字”に戻す

HTMLの世界では、特別な意味を持つ記号を「エンティティ」という形で表現します。

例えば:

  • <&lt;
  • >&gt;
  • &&amp;
  • "&quot;
  • '&#39;

エスケープは「記号 → エンティティ」への変換。
アンエスケープは「エンティティ → 記号」への変換です。

たとえば、ログやDBにこんな文字列が入っていたとします。

こんにちは &lt;b&gt;太郎&lt;/b&gt; さん

これをそのまま画面に出すと、「<b>」がそのまま見えてしまいます。
でも、人間が読みたいのは本来の形:

こんにちは <b>太郎</b> さん

この「元の形に戻す」のが、HTMLアンエスケープです。


C#での基本:HtmlDecode を使う

WebUtility.HtmlDecode の使い方

C# では、HTMLアンエスケープには主に次のAPIを使います。

  • System.Net.WebUtility.HtmlDecode
  • (ASP.NET系なら)System.Web.HttpUtility.HtmlDecode

ここでは依存の少ない WebUtility を使います。

using System;
using System.Net;

public static class HtmlUnescapeUtil
{
    public static string Unescape(string? value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return string.Empty;
        }

        return WebUtility.HtmlDecode(value);
    }
}
C#

動作例

Console.WriteLine(HtmlUnescapeUtil.Unescape("こんにちは <b>太郎</b> さん"));
// こんにちは <b>太郎</b> さん

Console.WriteLine(HtmlUnescapeUtil.Unescape("<script>alert('XSS');</script>"));
// <script>alert('XSS');</script>
C#

HtmlDecode は、&lt;&#39; のようなエンティティを自動的に解釈して、
元の文字に戻してくれます。


どんなものがアンエスケープされるのか

代表的なエンティティの変換

HtmlDecode は、HTMLで定義されているエンティティを解釈してくれます。
代表的なものは次の通りです。

  • &lt;<
  • &gt;>
  • &amp;&
  • &quot;"
  • &#39;'
  • &#x3042;(数値文字参照)

つまり、「& から始まって ; で終わる“特別な書き方”」を見つけて、
それを本来の文字に戻してくれるイメージです。

数値文字参照もちゃんと戻る

数値文字参照(&#数字;&#x16進数;)もアンエスケープされます。

Console.WriteLine(HtmlUnescapeUtil.Unescape("A"));      // A
Console.WriteLine(HtmlUnescapeUtil.Unescape("あ"));   // あ
C#

外部システムから「全部エンティティ化されたテキスト」が来ることもあるので、
こうしたケースでも HtmlDecode を通せば、普通の文字列として扱えるようになります。


HTMLエスケープとのセット運用を意識する

Encode → Decode の往復

HTMLエスケープ(Encode)とアンエスケープ(Decode)は、基本的にセットです。

using System.Net;

string original = "<b>太郎 & 次郎</b>";
string encoded  = WebUtility.HtmlEncode(original);
string decoded  = WebUtility.HtmlDecode(encoded);

Console.WriteLine(original); // <b>太郎 & 次郎</b>
Console.WriteLine(encoded);  // <b>太郎 & 次郎</b>
Console.WriteLine(decoded);  // <b>太郎 & 次郎</b>
C#

originalencodeddecoded とたどると、
元の文字列に戻っているのが分かります。

「どこでEncode」「どこでDecode」するかを決める

設計として大事なのは、

  • DBには「生の文字列」を保存するのか、「エスケープ済み」を保存するのか
  • 画面に出す直前で必ず HtmlEncode するのか
  • 外部から来たデータが「すでにエスケープ済み」なのか

を、層ごとにきちんと決めておくことです。

典型的なパターンは:

  • DB:生の文字列(エスケープしない)
  • HTML出力:ビュー側で HtmlEncode(=エスケープ)
  • 外部から「エスケープ済み文字列」が来たときだけ、必要に応じて HtmlDecode

アンエスケープは、「すべての文字列に対して毎回やるもの」ではなく、
“エスケープ済みのものを元に戻したいときだけ使う” という意識が大事です。


注意点:アンエスケープしたものをそのままHTMLに出さない

XSSの逆流に気をつける

例えば、外部からこんな文字列が来たとします。

&lt;script&gt;alert('XSS');&lt;/script&gt;

これを HtmlDecode すると、こうなります。

<script>alert('XSS');</script>

もし、これを そのままHTMLに埋め込んで表示してしまうと、
ブラウザは <script> として解釈し、JavaScriptを実行してしまいます。

つまり、

  • 「画面に出す前にアンエスケープ」してしまうと危険
  • 「画面に出すときは、Encode(エスケープ)された状態であるべき」

ということです。

アンエスケープは、

  • ログを読むために元の文字を見たい
  • テキスト処理(検索・置換など)をするために、エンティティを普通の文字に戻したい

といった「内部処理」向けに使うことが多いです。


業務ユーティリティとしてまとめる

Encode と Decode を同じ窓口にまとめる

プロジェクト全体で使う「HTML安全系ユーティリティ」を1つ用意しておくと、
どこで何をしているかが分かりやすくなります。

using System.Net;

public static class HtmlSafe
{
    public static string Encode(string? value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return string.Empty;
        }

        return WebUtility.HtmlEncode(value);
    }

    public static string Decode(string? value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return string.Empty;
        }

        return WebUtility.HtmlDecode(value);
    }
}
C#

使い分けのイメージはこんな感じです。

  • 画面に出すとき:HtmlSafe.Encode(model.Text)
  • 外部から「エスケープ済み文字列」が来たときに内部処理したい:HtmlSafe.Decode(input)

こうしておくと、「どこかで勝手に HtmlDecode してしまってXSSの入り口を作る」といった事故を減らせます。


まとめ 「HTMLアンエスケープユーティリティ」は“エンティティだらけの文字列を、人間が読める形に戻す道具”

HTMLアンエスケープは、HTMLエスケープの“逆操作”ですが、
使いどころを間違えるとセキュリティリスクにもつながります。

押さえておきたいポイントは、

  • アンエスケープは「&lt;&#39; を元の文字に戻す」処理
  • C#では WebUtility.HtmlDecode を使うのが基本
  • Encode ↔ Decode は往復可能だが、「どの層で何をするか」を決めておくことが重要
  • 画面に出す前に Decode してはいけない(XSSの原因になる)
  • Encode / Decode を1つのユーティリティにまとめて、使いどころを明確にする

ここまで理解できれば、「なんとなく HtmlDecode を呼んでいる」段階から一歩進んで、
“安全性と可読性のバランスを取った文字列処理”として、
HTMLアンエスケープを自分のC#ユーティリティにきちんと組み込めるようになっていきます。

タイトルとURLをコピーしました