Web.config 是 ASP.NET 應用程式的 **XML 格式設定檔**,採用**繼承與覆寫**機制:根目錄設定向下傳遞,子目錄可新增 Web.config 覆寫或擴充。修改後**無需重啟 IIS**(<processModel> 除外)即時生效,極利於生產環境熱更新。
<!-- 表單驗證:未登入導向登入頁 -->
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="30" name=".AspNetAuth" protection="All" />
</authentication>
<!-- 授權規則:順序敏感,先比對先生效 -->
<authorization>
<allow roles="Admin" /> <!-- 允許管理員 -->
<deny users="?" /> <!-- 拒絕匿名 -->
<allow users="*" /> <!-- 允許其餘已驗證用戶 -->
</authorization>
關鍵點:mode="Forms|Windows|Passport|None";<authorization> 可作用於資料夾/頁面層級,實現細粒度存取控制。
<compilation debug="false" targetFramework="4.8" batch="true" optimizeCompilations="true">
<assemblies>
<add assembly="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
debug="false":**生產環境強制關閉**,啟用會禁用編譯優化、產生 PDB、大幅降低效能。optimizeCompilations="true":僅重新編譯變更檔案,加速大型專案啟動。<!-- ASP.NET 管線錯誤 -->
<customErrors mode="RemoteOnly" defaultRedirect="~/Error/Index">
<error statusCode="404" redirect="~/Error/NotFound" />
<error statusCode="500" redirect="~/Error/ServerError" />
</customErrors>
<!-- IIS 管線錯誤(靜態檔案、URL 路由未命中等)-->
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
<remove statusCode="500" />
<error statusCode="500" path="/Error/ServerError" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
模式:On|Off|RemoteOnly(生產建議 RemoteOnly,本地除錯見詳細錯誤,遠端見友善頁)。
<httpRuntime
maxRequestLength="102400" <!-- 最大上傳 100MB (KB) -->
executionTimeout="300" <!-- 請求逾時 5 分鐘 -->
requestValidationMode="4.5" <!-- 請求驗證模式 -->
enableVersionHeader="false" <!-- 隱藏 X-AspNet-Version -->
targetFramework="4.8"
fcnMode="Disabled" <!-- 關閉檔案變更通知,避免 AppDomain 重啟 -->
/>
<pages
validateRequest="true" <!-- 請求驗證(防 XSS),MVC 通常在 Controller 以 [ValidateInput] 控制 -->
enableViewStateMac="true" <!-- ViewState 完整性驗證 -->
viewStateEncryptionMode="Auto" <!-- ViewState 加密 -->
controlRenderingCompatibilityVersion="4.0"
clientIDMode="AutoID"
/>
<!-- InProc:單機開發/低流量 -->
<sessionState mode="InProc" timeout="20" />
<!-- StateServer:跨伺服器共享,需啟動 ASP.NET State Service -->
<sessionState mode="StateServer" stateConnectionString="tcpip=10.0.0.1:42424" timeout="20" />
<!-- SQLServer:高可用、持久化,需執行 aspnet_regsql -->
<sessionState mode="SQLServer" sqlConnectionString="Data Source=...;Initial Catalog=ASPState;..." timeout="20" />
<!-- Custom:Redis 等第三方 -->
<sessionState mode="Custom" customProvider="RedisSessionProvider">
<providers>
<add name="RedisSessionProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" connectionString="..." />
</providers>
</sessionState>
<trace enabled="true" requestLimit="50" pageOutput="false" traceMode="SortByTime" localOnly="true" mostRecent="true" />
瀏覽 /trace.axd 查看請求時間軸、控制項樹、Session/Application 內容、資料庫查詢等。**生產環境務必 enabled="false"**。
<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=.;Database=MyDb;User=sa;Password=***;Encrypt=True;TrustServerCertificate=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="App:Environment" value="Production" />
<add key="App:MaxUploadSizeMB" value="100" />
<add key="Feature:NewDashboard" value="true" />
</appSettings>
讀取方式:
// 連線字串
var cs = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
// AppSettings
var env = ConfigurationManager.AppSettings["App:Environment"];
var maxSize = int.Parse(ConfigurationManager.AppSettings["App:MaxUploadSizeMB"]);
public class SmtpSettings : ConfigurationSection
{
[ConfigurationProperty("host", IsRequired = true)]
public string Host => (string)this["host"];
[ConfigurationProperty("port", DefaultValue = 587)]
public int Port => (int)this["port"];
[ConfigurationProperty("credentials", IsRequired = true)]
public CredentialsElement Credentials => (CredentialsElement)this["credentials"];
}
public class CredentialsElement : ConfigurationElement
{
[ConfigurationProperty("userName", IsRequired = true)]
public string UserName => (string)this["userName"];
[ConfigurationProperty("password", IsRequired = true)]
public string Password => (string)this["password"];
[ConfigurationProperty("enableSsl", DefaultValue = true)]
public bool EnableSsl => (bool)this["enableSsl"];
}
<configSections>
<section name="smtpSettings" type="MyApp.Config.SmtpSettings, MyApp" requirePermission="false" />
</configSections>
<smtpSettings>
<host>smtp.sendgrid.net</host>
<port>587</port>
<credentials userName="apikey" password="SG.xxx" enableSsl="true" />
</smtpSettings>
var smtp = (SmtpSettings)ConfigurationManager.GetSection("smtpSettings");
var client = new SmtpClient(smtp.Host, smtp.Port)
{
Credentials = new NetworkCredential(smtp.Credentials.UserName, smtp.Credentials.Password),
EnableSsl = smtp.Credentials.EnableSsl
};
專案包含 Web.Debug.config、Web.Release.config、Web.Staging.config 等,發佈時自動合併:
<!-- Web.Release.config -->
<configuration xmlns:xdt="https://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=prod-db;Database=MyDb;User=sa;Password=***;"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
<appSettings>
<add key="App:Environment" value="Production" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</configuration>
configSource 外部檔案:<appSettings configSource="configs\appsettings.prod.config" />(不納入版控)。| 項目 | 建議設定 | 風險 |
|---|---|---|
| debug | false | 洩露堆疊追蹤、效能下降 |
| customErrors | RemoteOnly + 自訂錯誤頁 | 資訊洩露 |
| requestValidation | true (MVC 局部關閉) | XSS 攻擊 |
| enableVersionHeader | false | 版本指紋識別 |
| machineKey | 明確指定 validationKey/decryptionKey | ViewState 偽造、跨應用驗證餅乾共享 |
| cookies | httpOnlyCookies="true" requireSSL="true" | XSS 竊取 Cookie、中間人攻擊 |
現代 ASP.NET Core 棄用 Web.config,改用 appsettings.json + 環境變數 + Key Vault,配置系統重寫為 IConfiguration 介面。遷移時:
<appSettings> → appsettings.json 結構化區段。<connectionStrings> → ConnectionStrings 區段。ConfigurationSection → POCO 類別 + IOptions<T> 模式。Web.config Transform → appsettings.{Environment}.json 疊加。