且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在Web API 2(ASP.Net Core)中实现基本身份验证?

更新时间:2022-12-06 16:47:25

我不确定您为什么说ASP.Net Core和Web API 2.我们通常不会在同一个项目中同时使用它们.

I'm not sure why you said ASP.Net Core and Web API 2. They are mutually exclusive; we don't normally use both in same project.

现在我的问题是是否有可能实施基本 Web API 2中进行身份验证?如果可能的话我能做到吗 动作过滤器又如何? Web身份验证的***方法是什么 API 2?我应该使用中间件吗?

Now my question is that is it possible to implement basic authentication in web API 2? If possible then can I achieve it with action filters and how? What is the best way to authentication in Web API 2? Should i use middle ware?

在Web API 2中,您可以使用 DelegatingHandler 轻松实现基本身份验证.

In Web API 2, you can easily implement Basic Authentication using DelegatingHandler.

这是示例代码-

public interface IBasicSecurityService
{
    bool SetPrincipal(string username, string password);
}

BasicSecurityService

public class BasicSecurityService : IBasicSecurityService
{
    public bool SetPrincipal(string username, string password)
    {
        // Get user from database
        var user = GetUser(username);
        IPrincipal principal = null;
        if (user == null || (principal = GetPrincipal(user)) == null)
        {
            // System could not validate user
            return false;
        }

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

        return true;
    }

    public virtual IPrincipal GetPrincipal(User user)
    {
        var identity = new GenericIdentity(user.Username, Constants.SchemeTypes.Basic);

        identity.AddClaim(new Claim(ClaimTypes.GivenName, user.Firstname));
        identity.AddClaim(new Claim(ClaimTypes.Surname, user.Lastname));
        // Get authroized roles and add them as Role Claim.
        identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));

        return new ClaimsPrincipal(identity);
    }
}

BasicAuthenticationMessageHandler

public class BasicAuthenticationMessageHandler : DelegatingHandler
{
    public const char AuthorizationHeaderSeparator = ':';
    private const int UsernameIndex = 0;
    private const int PasswordIndex = 1;
    private const int ExpectedCredentialCount = 2;

    private readonly IBasicSecurityService _basicSecurityService;

    public BasicAuthenticationMessageHandler(IBasicSecurityService basicSecurityService)
    {
        _basicSecurityService = basicSecurityService;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            // Already authenticated; passing on to next handler...
            return await base.SendAsync(request, cancellationToken);
        }

        if (!CanHandleAuthentication(request))
        {
            // Not a basic auth request; passing on to next handler...
            return await base.SendAsync(request, cancellationToken);
        }

        bool isAuthenticated;
        try
        {
            isAuthenticated = Authenticate(request);
        }
        catch (Exception e)
        {
            // Failure in auth processing
            return CreateUnauthorizedResponse();
        }

        if (isAuthenticated)
        {
            var response = await base.SendAsync(request, cancellationToken);
            return response;
        }

        return CreateUnauthorizedResponse();
    }

    public bool CanHandleAuthentication(HttpRequestMessage request)
    {
        return (request.Headers != null
                && request.Headers.Authorization != null
                && request.Headers.Authorization.Scheme.ToLowerInvariant() == Constants.SchemeTypes.Basic);
    }

    public bool Authenticate(HttpRequestMessage request)
    {
        // Attempting to authenticate...
        var authHeader = request.Headers.Authorization;
        if (authHeader == null)
        {
            return false;
        }

        var credentialParts = GetCredentialParts(authHeader);
        if (credentialParts.Length != ExpectedCredentialCount)
        {
            return false;
        }

        return _basicSecurityService.SetPrincipal(credentialParts[UsernameIndex], credentialParts[PasswordIndex]);
    }

    public string[] GetCredentialParts(AuthenticationHeaderValue authHeader)
    {
        var encodedCredentials = authHeader.Parameter;
        var credentialBytes = Convert.FromBase64String(encodedCredentials);
        var credentials = Encoding.ASCII.GetString(credentialBytes);
        var credentialParts = credentials.Split(AuthorizationHeaderSeparator);
        return credentialParts;
    }

    public HttpResponseMessage CreateUnauthorizedResponse()
    {
        var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(Constants.SchemeTypes.Basic));
        return response;
    }
}

信用: ASP.NET Web API 2:从头到尾构建REST服务.