如何在ASP.NET Core Web API中获取客户端域用户名?
ASP.NET Core Web API 自动获取客户端域用户名实现方案
要实现无客户端传参自动识别访问方域账号,核心依赖Windows集成身份验证(Kerberos/NTLM),域环境下客户端会自动和服务端完成认证握手,全程不需要客户端显式传递账号信息,拿到的身份是经过AD校验的,不存在伪造风险。
一、服务端基础配置
1. 服务注册
首先确保项目引用了Microsoft.AspNetCore.Authentication.Negotiate NuGet包,之后在Program.cs中注册认证服务:
var builder = WebApplication.CreateBuilder(args); // 注册Negotiate认证,自动处理域环境下的Kerberos/NTLM认证流程 builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate(); // 配置默认授权策略,拒绝匿名访问,确保所有请求都经过域身份校验 builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); // 注册控制器、你的AD查询服务等其他业务服务 builder.Services.AddControllers(); var app = builder.Build(); // 注意中间件顺序,认证授权中间件必须放在接口路由映射之前 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
2. 部署环境配置
- 如果直接用Kestrel自托管:不需要额外配置,上面的代码已经能正常处理认证请求
- 如果部署在IIS上:
- 先给IIS安装Windows认证角色功能:服务器管理器->添加角色和功能->Web服务器(IIS)->安全->勾选「Windows身份验证」,不需要的话直接禁用匿名身份验证
- 在发布后的
web.config中添加认证配置,避免IIS覆盖应用的认证规则:
<system.webServer> <security> <authentication> <anonymousAuthentication enabled="false" /> <windowsAuthentication enabled="true" /> </authentication> </security> </system.webServer>
二、接口中获取域用户名
认证流程完成后,直接通过Controller自带的User属性就能拿到当前访问用户的域账号,不需要额外解析请求头:
[ApiController] [Route("api/[controller]")] public class UserController : ControllerBase { [HttpGet("current")] public async Task<IActionResult> GetCurrentUser() { // 拿到完整域账号,格式为「域名\用户名」或「用户名@域后缀」 var fullAccount = User.Identity?.Name; if (string.IsNullOrWhiteSpace(fullAccount)) { return Unauthorized("未检测到有效域身份,请确认设备已加入域、使用域账号登录后访问"); } // 这里可以直接把fullAccount传给你已经对接好的AD服务查询用户信息 // 如果需要拆分域名和用户名做参数处理,可以参考以下逻辑 string domain = string.Empty, userName = string.Empty; if (fullAccount.Contains('\\')) { var parts = fullAccount.Split('\\', 2); domain = parts[0]; userName = parts[1]; } else if (fullAccount.Contains('@')) { var parts = fullAccount.Split('@', 2); userName = parts[0]; domain = parts[1]; } // 以下替换为你的AD查询逻辑 // var adUserInfo = await _adService.GetUserByAccount(domain, userName); return Ok(new { Domain = domain, UserName = userName, FullAccountName = fullAccount }); } }
三、常见踩坑点
- 客户端要求:访问设备必须加入服务端所在域,或者和服务端域有双向信任关系,且用户是用域账号登录的操作系统,浏览器、系统自带HTTP组件会自动完成凭据传递,不需要用户手动输入账号
- 非浏览器客户端调用:如果用HttpClient、Postman之类的工具调用,需要手动开启默认凭据传递,以HttpClient为例:
var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }); - 访问地址问题:Kerberos认证要求客户端用服务端的域内主机名访问,如果直接输IP地址,会降级到NTLM认证,部分域策略下会弹出认证框,甚至拿不到身份信息
- 不要自己解析Authorization头做认证判断:Negotiate中间件已经处理完所有校验逻辑,直接读
User.Identity.Name即可,自己解析容易出现校验不严格导致的账号伪造问题。
内容的提问来源于stack exchange,提问作者roundmoon88
相关产品推荐
相关产品推荐

