带有自定义身份验证的Web API 2 OAuth承载标记

我对C#Web API 2服务有以下要求:

作为认证的一个因素,该服务通过电子邮件和发送到其收件箱的临时密码的组合对用户进行身份验证。 我需要将此身份验证机制与生成OAuth承载标记融合,以确保服务的安全,并使用标准的ASP.NET授权机制通过某种[Authorize]属性检查每个请求与令牌的关系。

我已经成功实施了这些步骤

  • 用户请求密码
  • 系统生成30天到期的密码并通过电子邮件发送给用户
  • 用户使用电子邮件+密码进行身份验证
  • 系统检查密码的有效性
  • 但我不确定如何开始实施其余的步骤

  • 如果密码有效,系统会生成OAuth持票人标记
  • OAuth持票人令牌的持续时间与密码到期日期一样长
  • 使用ASP.NET身份验证属性来执行验证和授权检查
  • 使用OWIN安全和OAuth中间件创建令牌
  • 将基于声明的授权和序列化声明用于令牌
  • 引用的过程只描述使用ASP.NET身份个人用户帐户作为身份验证手段,而不是我想要如何进行身份验证。

    http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

    我其实需要通过检查电子邮件和密码进行身份验证。


    我在类似的场景中工作,并实现了一个认证过滤器( IAuthenticationFilter )和一个从OAuthAuthorizationServerProvider继承的定制类。 就我而言,我需要使用OAuth和传统令牌对请求进行身份验证。 我相信在你的情况下,你需要定制AuthenticationFilter 。 见下面的AuthenticationFilter一个例子:

    public class MyAuthenticationFilter : IAuthenticationFilter
    {
        private readonly string _authenticationType;
    
        /// <summary>Initializes a new instance of the <see cref="HostAuthenticationFilter"/> class.</summary>
        /// <param name="authenticationType">The authentication type of the OWIN middleware to use.</param>
        public MyAuthenticationFilter(string authenticationType)
        {
            if (authenticationType == null)
            {
                throw new ArgumentNullException("authenticationType");
            }
    
            _authenticationType = authenticationType;
        }
    
        /// <summary>Gets the authentication type of the OWIN middleware to use.</summary>
        public string AuthenticationType
        {
            get { return _authenticationType; }
        }
    
        /// <inheritdoc />
        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
    
            HttpRequestMessage request = context.Request;
    
            if (request == null)
            {
                throw new InvalidOperationException("Request mut not be null");
            }
    
    
            //In my case, i need try autenticate the request with BEARER token (Oauth)
            IAuthenticationManager authenticationManager = GetAuthenticationManagerOrThrow(request);
    
            cancellationToken.ThrowIfCancellationRequested();
            AuthenticateResult result = await authenticationManager.AuthenticateAsync(_authenticationType);
            ClaimsIdentity identity = null;
    
            if (result != null)
            {
                identity = result.Identity;
    
                if (identity != null)
                {
                    context.Principal = new ClaimsPrincipal(identity);
                }
            }
            else
            {
                //If havent success with oauth authentication, I need locate the legacy token
    //If dont exists the legacy token, set error (will generate http 401)
                if (!request.Headers.Contains("legacy-token-header"))
                    context.ErrorResult = new AuthenticationFailureResult(Resources.SAUTH_ERROR_LEGACYTOKENNOTFOUND, request);
                else
                {
                    try
                    {
                        var queryString = request.GetQueryNameValuePairs();
                        if (!queryString.Any(x => x.Key == "l"))
                            context.ErrorResult = new AuthenticationFailureResult(Resources.SAUTH_ERROR_USERTYPENOTFOUND, request);
                        else
                        {
                            var userType = queryString.First(x => x.Key == "l").Value;
                            String token = HttpUtility.UrlDecode(request.Headers.GetValues("tk").First());
    
                            identity = TokenLegacy.ValidateToken(token, userType);
                            identity.AddClaims(userType, (OwinRequest) ((OwinContext)context.Request.Properties["MS_OwinContext"]).Request);
                            if (identity != null)
                            {
                                context.Principal = new ClaimsPrincipal(identity);
                            }
                        }
    
                    }
                    catch (Exception e)
                    {
                        context.ErrorResult = new AuthenticationFailureResult(e.Message, request);
                    }
                }
            }
        }
    
    
        /// <inheritdoc />
        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
    
            HttpRequestMessage request = context.Request;
    
            if (request == null)
            {
                throw new InvalidOperationException("Request mut not be null");
            }
    
            IAuthenticationManager authenticationManager = GetAuthenticationManagerOrThrow(request);
    
            // Control the challenges that OWIN middleware adds later.
            authenticationManager.AuthenticationResponseChallenge = AddChallengeAuthenticationType(
                authenticationManager.AuthenticationResponseChallenge, _authenticationType);
    
            return TaskHelpers.Completed();
        }
    
        /// <inheritdoc />
        public bool AllowMultiple
        {
            get { return true; }
        }
    
        private static AuthenticationResponseChallenge AddChallengeAuthenticationType(
            AuthenticationResponseChallenge challenge, string authenticationType)
        {
            Contract.Assert(authenticationType != null);
    
            List<string> authenticationTypes = new List<string>();
            AuthenticationProperties properties;
    
            if (challenge != null)
            {
                string[] currentAuthenticationTypes = challenge.AuthenticationTypes;
    
                if (currentAuthenticationTypes != null)
                {
                    authenticationTypes.AddRange(currentAuthenticationTypes);
                }
    
                properties = challenge.Properties;
            }
            else
            {
                properties = new AuthenticationProperties();
            }
    
            authenticationTypes.Add(authenticationType);
    
            return new AuthenticationResponseChallenge(authenticationTypes.ToArray(), properties);
        }
    
        private static IAuthenticationManager GetAuthenticationManagerOrThrow(HttpRequestMessage request)
        {
            Contract.Assert(request != null);
    
            var owinCtx = request.GetOwinContext();
            IAuthenticationManager authenticationManager = owinCtx != null ? owinCtx.Authentication : null;
    
            if (authenticationManager == null)
            {
                throw new InvalidOperationException("IAuthenticationManagerNotAvailable");
            }
    
            return authenticationManager;
        }
    }
    

    WebApiConfig.cs ,您需要像这样添加认证过滤器:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
    
            config.Filters.Add(new MyAuthenticationFilter(OAuthDefaults.AuthenticationType));
         }
    }
    

    我建议阅读官方的WEB API海报:

    https://www.asp.net/media/4071077/aspnet-web-api-poster.pdf


    有关如何在asp.net Web API中设置身份验证的详细说明,请参阅此文章。 这应该给你一个关于如何在Web API中实现对你的需求的认证的好主意。 如果您有任何疑问或问题,请告诉我。

    谢谢,索玛。

    链接地址: http://www.djcxy.com/p/22395.html

    上一篇: Web API 2 OAuth Bearer Tokens with Custom Authentication

    下一篇: Authentication and authorization using WebApi