Windows Authentication下HttpContext.Current.User返回前访客信息问题求助
Windows身份验证内网网站身份混淆与凭据重复输入问题
环境信息
- .NET Framework: 4.6.1
- IIS: 10.0
问题背景
搭建了一个采用Windows身份验证的内网网站,配置如下:
- web.config指定Windows Authentication模式,拒绝匿名用户
- IIS启用Windows Authentication、禁用匿名访问,身份验证提供者为NTLM和Negotiate
网站首页是从SQL Server获取数据的表格,数据访问和权限过滤逻辑正常。IIS Express测试无问题,但部署到生产环境后出现异常。
异常现象
假设测试用户为userA(高权限)和userB(低权限):
- userA访问时,随机需要多次输入正确凭据(0-10次不等),甚至导致AD账号被无理由锁定;
- userA访问后,userB在另一台电脑访问网站,有时需要输入凭据有时不需要,但页面显示的用户名和数据都是userA的,多次刷新后才会切换为userB的信息。
已尝试的无效操作
每次修改后均重启了IIS应用池和站点:
- 切换使用
System.Web.HttpContext.Current.User.Identity.Name或User.Identity.Name获取用户名; - 给所有控制器方法添加
[Authorize]特性; - 在web.config和IIS中禁用站点缓存(
system.webServer/caching); - 在
system.webServer/security/authentication/windowsAuthentication中禁用authPersisNonNTLM和authPersistSingleRequest。
核心问题
User.Identity.Name或HttpContext.Current.User返回的是上一位访客的身份信息,而非当前访问用户的。
补充代码
控制器代码
public ActionResult List() { var username = System.Web.HttpContext.Current.User.Identity.Name; string userDisplayName = ADChecks.GetUserDisplayName(username); ViewBag.Message = "NewCommers List"; ViewBag.UserDisplayName = userDisplayName; return View(); }
页面代码
@model IEnumerable<NewComer.Models.NewComerModel> @{ ViewBag.Title = "New Comer - List"; } <p> @if (NewComer.App_Tools.ADChecks.IsRH(System.Web.HttpContext.Current.User.Identity.Name) || NewComer.App_Tools.ADChecks.IsAdmin(HttpContext.Current.User.Identity.Name)) { <div class="col-4"> <input type="button" value="Create New" class="btn btn-secondary valid w-100 mw-100" onclick="location.href='@Url.Action("Create", "Home")'" /> </div> } </p> <table id="ListViewTable" class="table table-responsive table-striped"> <thead> <tr> <th></th> <th>ID</th> <th>First Name</th> <th>Last Name</th> <th>Contract Type</th> <th data-bs-toggle="tooltip" data-bs-placement="top" title="MM/DD/YYYY">Date Start</th> <th data-bs-toggle="tooltip" data-bs-placement="top" title="MM/DD/YYYY">Date End</th> <th></th> <th></th> <th></th> </tr> </thead> </table>
页面通过$.ajax调用DataTables的LoadTable函数加载数据。
解决方案
1. 修正应用池配置
- 确认应用池托管管道模式为
集成,经典模式下Windows身份验证易出现身份混淆; - 应用池进程模型标识设为
ApplicationPoolIdentity,避免固定域账号导致身份复用; - 禁用应用池重叠回收:在IIS应用池高级设置中,将
启用重叠回收设为False,防止旧进程未退出时处理新请求。
2. 调整Windows身份验证配置
- 把
NTLM移到Negotiate之前,避免Kerberos协商失败反复弹出凭据框; - 启用内核模式身份验证,在web.config中添加:
<system.webServer> <security> <authentication> <windowsAuthentication enabled="true" useKernelMode="true"> <providers> <clear /> <add value="NTLM" /> <add value="Negotiate" /> </providers> </windowsAuthentication> </authentication> </security> </system.webServer>
3. 彻底禁用缓存
- 给控制器方法添加
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]特性,禁止输出缓存; - 在web.config添加响应头禁止客户端缓存:
<system.webServer> <httpProtocol> <customHeaders> <add name="Cache-Control" value="no-cache, no-store, must-revalidate" /> <add name="Pragma" value="no-cache" /> <add name="Expires" value="0" /> </customHeaders> </httpProtocol> </system.webServer>
4. 排查工具类静态状态
- 检查
ADChecks类的GetUserDisplayName、IsRH、IsAdmin方法是否使用静态变量存储用户数据,若有则移除静态缓存,确保每次调用都重新从AD获取信息。
5. 修复AJAX身份传递
- 确保AJAX请求启用
withCredentials,传递Windows身份验证凭据:$.ajax({ url: '/Home/LoadTable', type: 'GET', xhrFields: { withCredentials: true }, success: function(data) { // 数据处理逻辑 } });
6. 强制请求身份校验
- 在
Global.asax的Application_BeginRequest中添加身份校验,拒绝未验证请求:protected void Application_BeginRequest(object sender, EventArgs e) { if (!Request.IsAuthenticated) { Response.StatusCode = 401; Response.End(); } }
内容的提问来源于stack exchange,提问作者Boris GAUTHIER
相关产品推荐
相关产品推荐

