【问题标题】:How use AuthorizationFilterAttribute in WebApi with WebClient Library?如何将 WebApi 中的 AuthorizationFilterAttribute 与 WebClient 库一起使用?
【发布时间】:2017-10-04 17:42:32
【问题描述】:

我使用以下代码进行授权(我在互联网上找到并更改它以供我使用)

当我调用我的网址时,授权似乎有效

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class ClientAuthorizationAttribute : AuthorizationFilterAttribute
    {
        private bool _active = true;

        public ClientAuthorizationAttribute()
        {

        }

        public ClientAuthorizationAttribute(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;
                base.OnAuthorization(actionContext);
            }
        }

        protected virtual bool OnAuthorizeUser(string clientId, string authId, HttpActionContext actionContext)
        {
            return false;
        }
        protected virtual ClientAuthenticationIdentity 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.UTF8.GetString(Convert.FromBase64String(authHeader));

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

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

        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));
        }
    }

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

    public class BasicAuthorizationAttribute : ClientAuthorizationAttribute
    {

        public BasicAuthorizationAttribute()
        { }

        public BasicAuthorizationAttribute(bool active)
            : base(active)
        { }


        protected override bool OnAuthorizeUser(string clientId, string authId, HttpActionContext actionContext)
        {
            var businness = new WebServiceAuthBusiness();
            return businness.Count(x => x.ClientID == clientId && x.AuthenticateID == authId) > 0;
        }
    }
}

在客户端中,我使用 WebClient 获取应用程序数据(不起作用)

    [BasicAuthorization]
    public IList<Application> Get()
    {
        using (var client = new WebClient())
        {

            client.BaseAddress = _baseAddress;
            client.Encoding = Encoding.UTF8;
            client.UseDefaultCredentials = true; ???
            client.Credentials = new NetworkCredential(clientId, authId); ???
            var str = client.DownloadString("api/application/get");
            return JsonConvert.DeserializeObject<List<Application>>(str);
        }
    }

如何使用 webClient 为 AuthorizationFilter 发送用户名和密码???

【问题讨论】:

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


【解决方案1】:

c# corner所述:

在您的解决方案中添加 BasicAuthenticationAttribute.cs 类。

使用以下代码

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        try
        {
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
            else
            {
                // Gets header parameters  
                string authenticationString = actionContext.Request.Headers.Authorization.Parameter;
                string originalString = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationString));

                // Gets username and password  
                string usrename = originalString.Split(':')[0];
                string password = originalString.Split(':')[1];

                AuthsController auth = new AuthsController();
                // Validate username and password  
                if (!auth.ValidateUser(usrename, password))
                {
                    // returns unauthorized error  
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                }
            }

            base.OnAuthorization(actionContext);
        }
        // Handling Authorize: Basic <base64(username:password)> format.
        catch(Exception e)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }
}

在 AuthsController.cs(实体框架)中

添加

[NonAction]
    public bool ValidateUser(string userName, string password)
    {
        // Check if it is valid credential  
        var queryable = db.Auths
                        .Where(x => x.Name == userName)
                        .Where(x => x.Password == password);
        if (queryable != null)
        { 
            return true;
        }
        else
        {
            return false;
        }
    }

在 WebApiConfig.cs 中

添加

config.Filters.Add(new BasicAuthenticationAttribute());

在需要基本授权的控制器中。

添加

[BasicAuthentication]
public class YourController : ApiController{.......}

【讨论】:

  • 由于外部链接可以提供有效答案,请在此处添加帖子的主要代码。如果将来该链接断开,则此答案对其他用户将毫无用处。谢谢
  • 编辑答案@acostela
  • 添加 config.Filters.Add(new BasicAuthenticationAttribute());在全局配置中或使用 BasicAuthentication 属性装饰您的控制器。为什么两者都有?
  • 我已经设置了所有这些,但是没有授权标头的请求返回 200,我可能缺少什么?
【解决方案2】:

基本认证需要Authorization header to be set

using (var client = new WebClient())
{    
    var credential = String.Format("{0}:{1}", userName, password);
    var encodedCredential = Convert.ToBase64String(Encoding.UTF8.GetBytes(credential))    
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedCredential);

    // ...
}

【讨论】:

  • 将字符串编码为 base64 的意义何在?它增加了零安全性,但占用了 33% 以上的空间(任何 ASCII 字符在 UTF-8 中都需要一个字节,但需要四个字符才能将三个字节表示为 base64)。
  • base64 编码是 BASIC 身份验证协议的要求:ietf.org/rfc/rfc2617.txt 要接收授权,客户端会在 base64 [7 ] 凭据中的编码字符串。
  • @TheDag,如果你还没有弄清楚。 Base64 使得通常无法通过 HTTP 发送的字符可以通过将它们编码为允许的基本字符来发送。
【解决方案3】:

您应该能够将用户名和加密密码作为 GET api URL 的一部分发送。

/api/application/Get?user=''&pw=''

您的 AuthorizationFilter 应该能够从 RequestUri 解析它们,但当然您永远不想这样做,相反您可能需要实现 OAuth Token 样式 access token 与您的 API 一起发送。基本上,您的用户将使用登录面板并通过 https 发布登录详细信息并接收令牌,然后每次他或她发出请求时都会发送访问令牌以及该 API,如下所示:

/api/application/Get?access_token=""

此访问令牌可能会在特定时间段或速率限制后过期。 你可以在这里找到一个实现:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2012-10-18
    • 2019-09-08
    相关资源
    最近更新 更多