核心思想:分层防御
网站权限设置不是单一操作,而是一个“纵深防御”体系,每个层面都有其职责,共同确保网站的安全。

(图片来源网络,侵删)
- 操作系统层面:最底层,控制文件和进程的访问权限。
- IIS 服务器层面:Web 服务器层面,控制匿名访问、身份验证方式、URL 授权等。
- 应用程序代码层面:最高层,实现业务逻辑级别的权限控制(用户A只能编辑自己的文章)。
操作系统权限
这是基础,如果这里没做好,上层的安全措施可能会被绕过。
应用程序池标识
你的 ASP.NET 应用程序运行在某个“应用程序池”中,这个应用程序池有一个“进程标识”(Process Identity),决定了它以哪个用户的身份在操作系统上运行。
- 默认设置:通常是
NETWORK SERVICE,这是一个受限账户,比SYSTEM或Administrator安全得多。 - 最佳实践:
- 不要将应用程序池标识设置为
SYSTEM或管理员账户,除非有特殊且必要的原因。 - 为每个网站创建专用用户:如果多个网站共享一个服务器,为每个网站的应用程序池创建一个独立的、低权限的 Windows 用户,这样可以隔离风险,一个网站被攻破,不会影响到其他网站。
- 权限分配:为这个专用用户分配最小的必要权限,只给它读取网站程序文件和写入
App_Data文件夹的权限,而不要给整个C:盘的写入权限。
- 不要将应用程序池标识设置为
文件和文件夹权限
在 Windows 资源管理器中,右键点击网站文件夹 -> 属性 -> 安全 选项卡。
- 网站根目录 (e.g.,
C:\inetpub\wwwroot\MyWebApp):IIS_IUSRS组:必须拥有 读取 和执行、列出文件夹内容、读取 权限,这是 IIS 用来执行你的网站代码所必需的。- 应用程序池用户:如果你为网站创建了专用用户,则该用户需要上述权限。
SYSTEM和Administrators:拥有完全控制权,方便管理和维护。Users组:通常需要读取权限,但需要根据具体情况评估。
App_Data文件夹:- 这个文件夹通常用于存放数据库文件(.mdf, .dbf)或敏感数据。
- 移除
Everyone和Users的所有权限。 - 只授予 应用程序池用户 和
SYSTEM完全控制 权限,确保你的网站代码能读写,但其他任何人都不能访问。
- Web.config 文件:
- 这是一个非常敏感的文件,包含数据库连接字符串、加密密钥等。
- 只授予 应用程序池用户 和
SYSTEM读取 权限,其他用户(包括IIS_IUSRS)都不需要读取权限。
IIS 服务器权限
在 IIS 管理器中进行配置。

(图片来源网络,侵删)
身份验证
在 IIS 管理器中,选择你的网站 -> IIS -> 身份验证。
- 匿名身份验证:
- 作用:允许任何用户访问网站,无需登录。
- 如何工作:它会使用一个固定的账户(默认是
IUSR)来访问服务器资源。 - 配置:
- 对于公开网站:必须启用。
- 对于内部网站:可以禁用。
- 最佳实践:不要将匿名账户设置为高权限账户(如管理员),让它保持默认的
IUSR或映射到你之前创建的专用低权限用户。
- Windows 身份验证:
- 作用:使用 Windows 用户账户进行登录验证。
- 类型:有“Negotiate”(Kerberos)和“NTLM”两种,前者更安全,性能也更好。
- 适用场景:企业内部网,用户已经在同一个 Windows 域中,可以使用域账户登录。
- 配置:在启用此选项时,通常会禁用匿名身份验证。
- ASP.NET Core 模拟:
- 在 IIS 中,你可以选择是否“模拟”。
- 如果选择“模拟”,ASP.NET 应用程序将以你配置的身份(匿名用户或 Windows 用户)的身份运行,去访问操作系统文件。
- 如果不选择“模拟”(默认),那么应用程序将以应用程序池的身份运行。
- 建议:通常不启用模拟,让应用程序以应用程序池的身份运行,权限管理更清晰。
授权
在 IIS 管理器中,选择你的网站 -> 功能视图 -> 授权规则。
- 作用:基于 URL 路径控制哪些用户或角色可以访问哪些页面或文件夹。
- 示例:
- 你可以创建一条规则,拒绝所有匿名用户访问
Admin文件夹。 - 你可以创建一条规则,只允许
Administrators角色访问/Dashboard.aspx页面。
- 你可以创建一条规则,拒绝所有匿名用户访问
- 使用方法:点击“添加授权规则”,可以选择“允许”或“拒绝”,然后指定用户/角色或匿名用户。
应用程序代码层面
这是最灵活、最精细的控制方式。
ASP.NET Forms Authentication (Web Forms / MVC 早期版本)
这是经典的基于 Cookie 的身份验证方式。
- 配置
Web.config:- 在
<system.web>节点下配置:<authentication mode="Forms"> <forms loginUrl="~/Account/Login.aspx" timeout="30" slidingExpiration="true" /> </authentication>
loginUrl:未登录用户被重定向到的登录页。<authorization>节点:在页面或文件夹级别进行授权。<!-- 允许所有人访问 --> <allow users="*" /> <!-- 拒绝匿名用户访问 --> <deny users="?" /> <!-- 拒绝特定用户 --> <deny users="SomeBadUser" /> <!-- 允许特定角色 --> <allow roles="Admin, Manager" /> <!-- 拒除特定角色 --> <deny roles="Guest" />
- 在
- 登录逻辑:
- 在登录页面,验证用户名和密码。
- 验证成功后,调用
FormsAuthentication.SetAuthCookie(username, rememberMe)来创建身份验证票证(Cookie)。
- 检查登录状态:
- 在页面的代码中,使用
Page.User.Identity.IsAuthenticated来判断用户是否已登录。
- 在页面的代码中,使用
ASP.NET Identity (ASP.NET MVC / Core 推荐方案)
这是现代的、基于角色的成员资格提供程序,更强大、更灵活。
-
核心概念:
- 用户:
IdentityUser类,包含用户名、密码、邮箱等。 - 角色:
IdentityRole类,如 "Admin", "User", "Editor"。 - 用户-角色关系:一个用户可以属于多个角色。
- 用户:
-
配置:
- 通过 NuGet 安装
Microsoft.AspNetCore.Identity.EntityFrameworkCore等包。 - 在
Startup.cs(或Program.csin .NET 6+) 中配置服务和中间件。
- 通过 NuGet 安装
-
授权方式:
-
特性授权:在 Controller 或 Action 方法上使用特性,这是最简洁的方式。
// 要求用户已登录 [Authorize] public IActionResult Profile() { ... } // 要求用户属于 "Admin" 角色 [Authorize(Roles = "Admin")] public IActionResult Dashboard() { ... } // 要求用户是特定用户名 [Authorize(Policy = "CanEditOnlyOwnProfile")] public IActionResult EditProfile() { ... } -
基于策略的授权:更复杂、更灵活的授权方式,你可以定义一个策略,然后在代码中检查该策略。“用户必须年满18岁”或“用户必须通过双重验证”。
// 在 Startup.ConfigureServices 中定义策略 services.AddAuthorization(options => { options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin")); }); // 在 Controller 中使用 [Authorize(Policy = "RequireAdminRole")] public IActionResult AdminOnlyArea() { ... } -
资源授权:在 Action 方法内部进行授权检查,适用于复杂的业务逻辑。
public async Task<IActionResult> EditArticle(int id) { var article = await _context.Articles.FindAsync(id); if (article == null) { return NotFound(); } // 检查当前用户是否是文章作者或管理员 if (User.IsInRole("Admin") || User.FindFirstValue(ClaimTypes.NameIdentifier) == article.AuthorId) { return View(article); } return Forbid(); // 返回 403 Forbidden }
-
总结与最佳实践清单
-
从操作系统开始:
- [ ] 使用低权限的应用程序池标识(
NETWORK SERVICE或专用用户)。 - [ ] 严格设置文件和文件夹权限,特别是
App_Data和Web.config。
- [ ] 使用低权限的应用程序池标识(
-
配置 IIS:
- [ ] 根据网站类型(公开/内部)正确配置匿名和 Windows 身份验证。
- [ ] 使用 IIS 的 URL 授权功能对敏感目录(如
/Admin)进行粗粒度访问控制。
-
编写代码进行精细控制:
- [ ] 对于新项目,优先使用 ASP.NET Identity。
- [ ] 在 Controller 上使用
[Authorize]特性保护需要登录的页面。 - [ ] 使用
[Authorize(Roles = "...")]来基于角色控制访问。 - [ ] 对于复杂业务逻辑(如“只能修改自己的数据”),使用基于策略的授权或资源授权。
- [ ] 永远不要在代码中硬编码用户名或密码,使用 Identity 或其他安全的认证库。
- [ ] 对密码进行哈希处理(Identity 会自动处理)。
- [ ] 使用 HTTPS 来保护传输中的身份验证 Cookie 和敏感数据。
通过遵循以上三个层面的设置,你可以构建一个既安全又灵活的 ASP.NET 网站权限系统。
