【问题标题】:Is it possible to secure a web api with Authentication Filters using the local AD system acounts?是否可以使用本地 AD 系统帐户通过身份验证过滤器保护 Web api?
【发布时间】:2016-03-08 21:02:56
【问题描述】:

我已经研究了一种方法来模拟您的 AD 用户,以使用我的本地域 AD 保护我的 Web API。 我发现的所有示例都使用基本身份验证或令牌身份验证。或使用 Azure AD 保护它。

我想使用我的本地域 AD/Impersonation 来实现我的自定义授权业务逻辑。我所能实现的就是使用 BASIC 身份验证,并且挑战总是弹出一个表单来输入用户名/密码。我想绕过它并使用我的本地域 + 自定义逻辑来验证/授权用户。

有没有一种方法可以模拟 windows 用户在我的 web api 中对资源进行身份验证和授权?

这是我的挑战功能的样子:

 void Challenge(HttpRequestMessage request, HttpResponseMessage response)
    {
        var host = request.RequestUri.DnsSafeHost;
        response.Headers.Add(WWWAuthenticateHeader, string.Format("Basic realm=\"{0}\"", host));
    }

非常感谢!

【问题讨论】:

    标签: authentication asp.net-web-api active-directory basic-authentication


    【解决方案1】:

    首先,您应该阅读以下内容:

    How to get HttpClient to pass credentials along with the request?

    第二(如果你正在做“单跳”)。

    如果启用“Windows 身份验证”并禁用“匿名身份验证”(在 IIS 中的“身份验证”下)......您可以获取 Windows 身份。

    您需要编写一个自定义 AuthorizeAttribute。

    这是一个基本的尝试:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Http;
    using System.Web.Http.Controllers;
    
    namespace MyLibrary.CustomAttributes.WebApi
    {
        public class IdentityWhiteListAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
        {
            public const string ErrorMessageBadIdentityContent = "IIdentity.Name was empty or IIdentity was not a WindowsIdentity. CurrentAction='{0}'";
            public const string ErrorMessageBadIdentityReasonPhrase = "IIdentity.Name was empty or IIdentity was not a WindowsIdentity.  The most likely reason is that the web service is not setup for WindowsAuthentication and/or Anonymous Authentication is enabled.";
    
            public const string ErrorMessageNotAuthenticated = "IIdentity.IsAuthenticated was false. '{0}'";
    
            public IdentityWhiteListAuthorizationAttribute()
            {
            }
    
            private string CurrentActionName { get; set; }
    
            public override void OnAuthorization(HttpActionContext actionContext)
            {
                this.CurrentActionName = actionContext.ActionDescriptor.ActionName;
                base.OnAuthorization(actionContext);
            }
    
            protected override bool IsAuthorized(HttpActionContext actionContext)
            {
    
                /* this will authenticate if the authorization-header contained a "Negotiate" windows Identity.  Note, WebApi must be running in Windows-Authentication mode (and the WebApi-web.config must be set for "<authentication mode="Windows" />") for this to work.  (the client will send the windows identity via the DefaultRequestHeaders.Authorization header */
    
                string currentActionName = this.CurrentActionName;
                IPrincipal httpContextCurrentUserPrinc = HttpContext.Current.User; /*  */
                IIdentity ident = httpContextCurrentUserPrinc.Identity;
    
                bool badIdentity = false;
    
                string errorMessageContent = string.Empty;
                string errorMessageReasonPhrase = string.Empty;
    
                if (null == ident)
                {
                    badIdentity = true;
                    errorMessageContent = string.Format(ErrorMessageBadIdentityContent, currentActionName);
                    errorMessageReasonPhrase = ErrorMessageBadIdentityReasonPhrase;
                }
    
                if (!badIdentity)
                {
                    /* Ensure that we have an actual userName which means windows-authentication was setup properly */
                    if (string.IsNullOrEmpty(ident.Name))
                    {
                        badIdentity = true;
                        errorMessageContent = string.Format(ErrorMessageBadIdentityContent, currentActionName);
                        errorMessageReasonPhrase = ErrorMessageBadIdentityReasonPhrase;
                    }
                }
    
                if (!badIdentity)
                {
                    if (!ident.IsAuthenticated)
                    {
                        badIdentity = true;
                        errorMessageContent = string.Format(ErrorMessageNotAuthenticated, ident.Name);
                        errorMessageReasonPhrase = string.Format(ErrorMessageNotAuthenticated, ident.Name);
                    }
                }
    
                if (!badIdentity)
                {
                    if (ident.GetType() != typeof(WindowsIdentity))
                    {
                        badIdentity = true;
                        errorMessageContent = string.Format(ErrorMessageBadIdentityContent, currentActionName);
                        errorMessageReasonPhrase = ErrorMessageBadIdentityReasonPhrase;
                    }
                }
    
                if (badIdentity)
                {
                    HttpResponseMessage resp = new HttpResponseMessage(HttpStatusCode.BadRequest)
                    {
                        Content = new StringContent(errorMessageContent),
                        ReasonPhrase = errorMessageReasonPhrase
                    };
                    throw new HttpResponseException(resp);
                }
    
    
                return true;
    
    
    
            }
        }
    }
    

    将该属性应用于 webapi 控制器和/或方法。

    您也可以编写一个 DelegatingHandler...并使用上面相同的代码......

    【讨论】:

    • 非常感谢伙计...这非常有用。在这种情况下使用委托处理程序有什么好处?我想在某处编写我的自定义授权例程。您是否建议在“IsAuthorized”事件中这样做?再次感谢您的帮助!干杯!
    • 委托处理程序(一旦添加)..将影响每个控制器/动作。属性方式(在我的帖子上方)让您选择。委托处理程序在管道中较早运行。如果每个控制器/操作都需要安全检查.....那么请使用委托处理程序。
    猜你喜欢
    • 2020-07-04
    • 1970-01-01
    • 2017-02-04
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    相关资源
    最近更新 更多