是否可以使用本地 AD 系统帐户通过身份验证过滤器保护 Web api?

Posted

技术标签:

【中文标题】是否可以使用本地 AD 系统帐户通过身份验证过滤器保护 Web api?【英文标题】:Is it possible to secure a web api with Authentication Filters using the local AD system acounts? 【发布时间】: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));
    

非常感谢!

【问题讨论】:

【参考方案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”事件中这样做?再次感谢您的帮助!干杯! 委托处理程序(一旦添加)..将影响每个控制器/动作。属性方式(在我的帖子上方)让您选择。委托处理程序在管道中较早运行。如果每个控制器/操作都需要安全检查.....那么请使用委托处理程序。

以上是关于是否可以使用本地 AD 系统帐户通过身份验证过滤器保护 Web api?的主要内容,如果未能解决你的问题,请参考以下文章

Azure AD 身份验证令牌未通过 Web api 授权

Azure AD Connect 用户登录选项介绍

使用Azure AD验证个人MS帐户时,无法使用特定于租户的端点

本地 SQL 和 Windows 身份验证的不同模拟

MVC Web 应用程序 - Azure AD 和外部帐户

Azure AD:50155 设备身份验证失败