为ASP.NET Web API 2应用程序启用Windows和基本身份验证

时间:2017-01-18 20:24:12

标签: c# asp.net asp.net-mvc authentication asp.net-web-api

我有一个ASP.NET Web API 2应用程序,它为所有控制器使用Windows身份验证。我现在需要某些控制器使用基本身份验证。

我知道无法同时启用匿名和Windows身份验证,但是是否可以为某些控制器启用Windows身份验证,为其他控制器启用基本身份验证?

更新: 实现了文章EdSF shared

所示的过滤器

这是我到目前为止所做的:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class BasicAuthenticationFilter : AuthorizationFilterAttribute
{
    private bool _active = true;
    private const string ValidUsername = @"Test";
    private const string ValidPassword = @"T3st";

    public BasicAuthenticationFilter()
    {
    }

    public BasicAuthenticationFilter(bool active)
    {
        _active = active;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (_active)
        {
            var identity = ParseAuthorizationHeader(actionContext);
            if (identity == null)
            {
                Challenge(actionContext);
                return;
            }


            if (!OnAuthorizeUser(identity.Name, identity.Password, actionContext))
            {
                Challenge(actionContext);
                return;
            }

            var principal = new GenericPrincipal(identity, null);

            Thread.CurrentPrincipal = principal;

            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }

            base.OnAuthorization(actionContext);
        }
    }

    protected virtual bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
    {
        if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password) ||
            !username.Equals(ValidUsername) || !password.Equals(ValidPassword))
        {
            return false;
        }

        return true;
    }

    protected virtual BasicAuthenticationIdentity ParseAuthorizationHeader(HttpActionContext actionContext)
    {
        string authHeader = null;
        var auth = actionContext.Request.Headers.Authorization;
        if (auth != null && auth.Scheme == "Basic")
        {
            authHeader = auth.Parameter;
        }

        if (string.IsNullOrEmpty(authHeader)) return null;

        authHeader = Encoding.Default.GetString(Convert.FromBase64String(authHeader));

        var tokens = authHeader.Split(':');
        if (tokens.Length < 2) return null;

        return new BasicAuthenticationIdentity(tokens[0], tokens[1]);
    }

    private void Challenge(HttpActionContext actionContext)
    {
        var host = actionContext.Request.RequestUri.DnsSafeHost;
        actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        actionContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", host));
    }
}

BasicAuthenticationIdentity类:

public class BasicAuthenticationIdentity : GenericIdentity
{
    public BasicAuthenticationIdentity(string name, string password)
        : base(name, "Basic")
    {
        Password = password;
    }

    public string Password { get; set; }
}

另外,使用基本身份验证过滤器装饰我的控制器:

[BasicAuthenticationFilter]
[RoutePrefix("api/BasicAuth")]
public class BasicAuthController : ApiController
{
    //[BasicAuthenticationFilter]
    [HttpGet]
    public IHttpActionResult TestBasicAuth()
    {
        return Ok("success");
    }
}

当我从Fiddler打电话给api / BasicAuth时,我回到了401,但它只会带来以下挑战:

WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM

此时Fiddler再次尝试,但这次不是通过基本授权方案,而是通过Negotiate。这个也失败了。

然后,当Fiddler最后第三次尝试时,我的过滤器实际上得到了请求,但由于授权方案是Negotiate而不是Basic,我的过滤器也返回Unauthorized。

有没有办法强制控制器只使用BasicAuthenticationFilter?

提前致谢

1 个答案:

答案 0 :(得分:0)

您可以 - 因为BASIC AUTH凭据是在HTTP Headers中发送的(仅限base64编码)。你不 to&#34;启用&#34;应用程序级别的任何内容,并处理对API端点的HTTP请求&#34;手动&#34; (通过检查标题)。

e.g。基本身份验证标头:Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

请参阅创建AuthorizationFilter Controller的{​​{1}},该Action可应用于myDomain.comHost,甚至可在全球范围内应用... {/ p>

H个。