如何根据 Authorization 标头值授权请求?

Rey*_*van 1 .net c# authorization asp.net-core

我正在尝试使用 ASP.NET Core 提出一个简单的 API,我想根据请求的授权标头限制对某些端点的访问。

在 ASP.NET MVC5 中,我可以通过继承AuthorizationFilterAttribute和覆盖 check 方法来做到这一点,就像这样:

public class BasicAuthorizationAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        try
        {
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                return;
            }

            var authorizationToken = Encoding.UTF8.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter)).Split(':');
            var username = authorizationToken[0];
            var password = authorizationToken[1];
            if (SecurityHelper.Login(username, password))
            {
                Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username), null);
                actionContext.RequestContext.Principal = Thread.CurrentPrincipal;
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                return;
            }
        } catch
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            return;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但从表面上看,Core 使用了一个完全不同的授权系统,它似乎需要更多的代码,而且设置似乎并不打算与标头检查一起使用。对于这种情况,整个 Policy 系统似乎过于复杂。这是我应该在这种情况下使用的吗?或者是否有一些内置的替代方法来检查基本身份验证?

谢谢!

Nan*_* Yu 8

您无需将 header 添加为 claim ,您可以通过将 an 的实例注入IHttpContextAccessor到您的 中来访问授权标头AuthorizationHandler

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    IHttpContextAccessor _httpContextAccessor = null;
    public MinimumAgeHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                    MinimumAgeRequirement requirement)
    {

        HttpContext httpContext = _httpContextAccessor.HttpContext;

        string authHeader = httpContext.Request.Headers["Authorization"];
        if (authHeader != null && authHeader.StartsWith("Basic "))
        {
            // Get the encoded username and password
            var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
            // Decode from Base64 to string
            var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
            // Split username and password
            var username = decodedUsernamePassword.Split(':', 2)[0];
            var password = decodedUsernamePassword.Split(':', 2)[1];
            // Check if login is correct

        }

        ........

        if (.....)
        {
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能需要在 DI setup 中注册它,如下所示:

services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)