利用 HttpResponse.Filter 可在輸出串流階段統一替換敏感詞,優點是無需修改既有業務邏輯,缺點是敏感詞仍會寫入資料庫。本文示範自訂 Stream 實作全站關鍵字替換。
public class ResponseFilter : Stream
{
private Stream _responseStream;
private long _position;
private readonly StringBuilder _html = new StringBuilder();
public ResponseFilter(Stream inputStream) { _responseStream = inputStream; }
#region Stream 抽象成員實作
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => true;
public override long Length => 0;
public override long Position { get => _position; set => _position = value; }
public override void Close() => _responseStream.Close();
public override void Flush() => _responseStream.Flush();
public override long Seek(long offset, SeekOrigin dir) => _responseStream.Seek(offset, dir);
public override void SetLength(long len) => _responseStream.SetLength(len);
public override int Read(byte[] buf, int off, int cnt) => _responseStream.Read(buf, off, cnt);
#endregion
public override void Write(byte[] buffer, int offset, int count)
{
// 取得輸出字串
string sBuffer = Encoding.UTF8.GetString(buffer, offset, count);
// 敏感詞清單(實務建議從資料庫或 Web.config 讀取)
string pattern = @"(敏感詞1|敏感詞2|敏感詞3)";
foreach (string word in pattern.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
{
sBuffer = sBuffer.Replace(word, "**");
}
// 寫回原始串流
byte[] data = Encoding.UTF8.GetBytes(sBuffer);
_responseStream.Write(data, 0, data.Length);
}
}
在 Global.asax 的 Application_BeginRequest 掛載過濾器:
public void Application_BeginRequest()
{
Response.Filter = new ResponseFilter(Response.Filter);
}
Content-Type 略過過濾。StringBuilder 累積後一次寫入,減少記憶體壓力。