【问题标题】:ASP.NET Web API 2 -> Windows Authentication -> Impersonate Windows user on AzureASP.NET Web API 2 -> Windows 身份验证 -> 在 Azure 上模拟 Windows 用户
【发布时间】:2026-02-22 01:35:01
【问题描述】:

我们正在使用Windows Authentication 开发一个在公司内部使用的应用程序。我们已经查看了ADFS,但目前这不是一个选项。问题是我们的测试服务器完全是基于Azure 的云。我一直在尝试寻找激活用户的方法,但没有找到好的解决方案。

我的第一个想法是完全关闭authentication。这很好用,但我们有一些资源可以检查用户角色,所以我不得不放弃这个想法。

<system.web>
  <authentication mode="None" />
</system.web>

返回401 Unauthorizedauthentication mode="None" 的示例方法,显然:

[Authorize(Roles = "Administrator")]
[HttpGet]
[Route("TestMethod")]
public IHttpActionResult TestMethod()
{
    return Ok("It works!");
}

我的第二个想法是编辑WebApiConfig 并尝试在每个请求服务器端添加身份验证标头。然而,当我开始查看 NTLM Authentication Scheme for HTTP 和 4 次握手时,我意识到这可能是不可能的。

NTLM Authentication Scheme for HTTP

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Other code for WebAPI registerations here
        config.MessageHandlers.Add(new AuthenticationHandler());  
    }
}

class AuthenticationHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Add authentication to every request...
        return base.SendAsync(request, cancellationToken);
    }
}

由于没有Owin (Katana),我无法编辑标准的 App_Start -> Startup.Auth.cs -> public void ConfigureAuth(IAppBuilder app) 并在那里尝试一些东西。无论如何,我不知道如何构建“用户对象”。

对此我们有什么可以做的,还是我们必须在本地测试所有内容?如果我们可以为每个请求模拟一个用户登录,这在测试环境中就可以了。

【问题讨论】:

    标签: c# asp.net azure authentication windows-authentication


    【解决方案1】:

    在伪造身份验证和授权方面,您应该能够使用 FilterAttribute 设置具有适当角色的通用用户主体。

    public class TestIdentityFilter :  FilterAttribute, IAuthenticationFilter
    {
        public void OnAuthentication(AuthenticationContext filterContext)
        {
            filterContext.Principal = new GenericPrincipal(
                new GenericIdentity(),
                new string [] {"Administrator"});
        }
    }
    

    您需要像以前一样设置&lt;authentication mode="None" /&gt;,否则此代码将永远不会在您的测试环境中被命中。

    将此添加为全局过滤器将覆盖任何其他现有的身份验证系统(例如,如果您错误地将其部署到经过身份验证的环境中)。显然,您需要非常小心,只在您的测试系统中使用它。

    这个例子是基于 MVC 的,我认为和 WebApi 有一些非常小的差异,但是基本原理是适用的。

    【讨论】:

    • 非常感谢您为我指明了正确的方向。用工作代码自己发布了一个答案。
    【解决方案2】:

    非常感谢@ste-fu 为我指明了正确的方向。完整代码:

    public class AppSettingsDynamicRolesAuthorizeAttribute : AuthorizeAttribute
    {
        public AppSettingsDynamicRolesAuthorizeAttribute(params string[] roleKeys)
        {
            List<string> roles = new List<string>(roleKeys.Length);
    
            foreach (var roleKey in roleKeys)
            {
                roles.Add(WebConfigurationManager.AppSettings[roleKey]);
            }
    
            this.Roles = string.Join(",", roles);
        }
    
        public override void OnAuthorization(HttpActionContext filterContext)
        {
            if (Convert.ToBoolean(WebConfigurationManager.AppSettings["IsTestEnvironment"]))
            {
                filterContext.RequestContext.Principal = new GenericPrincipal(
                    new GenericIdentity("Spoofed-Oscar"),
                    new string[] { WebConfigurationManager.AppSettings[Role.Administrator] });
            }
    
            base.OnAuthorization(filterContext);
        }
    }
    
    public static class Role
    {
        public const string Administrator = "Administrator";
        public const string OtherRole = "OtherRole";
    }
    

    然后可以这样使用:

    [AppSettingsDynamicRolesAuthorize(Role.Administrator, Role.OtherRole)]
    [HttpGet]
    [Route("Test")]
    public IHttpActionResult Get()
    {
    
        var userName = RequestContext.Principal.Identity.Name;
    
        var user = HttpContext.Current.User.Identity;
    
        return Ok("It works!");
    }
    

    【讨论】: