程序旅途

ASP.NET Web Api实现Http基本认证

Http基本认证介绍

Http基本认证,Http Basic Authenticate,关于它的一些概念,还是直接参考维基百科吧。

为了文章稍微看起来完整一些,下面一段的内容摘自维基百科:

在HTTP中,基本认证是一种用来允许Web浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。

在发送之前是以用户名追加一个冒号然后串接上口令,并将得出的结果字符串再用Base64算法编码。例如,提供的用户名是Aladdin、口令是open sesame,则拼接后的结果就是Aladdin:open sesame,然后再将其用Base64编码,得到QWxhZGRpbjpvcGVuIHNlc2FtZQ==。最终将Base64编码的字符串发送出去,由接收者解码得到一个由冒号分隔的用户名和口令的字符串。

最初,基本认证是定义在HTTP 1.0规范(RFC 1945)中,后续的有关安全的信息可以在HTTP 1.1规范(RFC 2616)和HTTP认证规范(RFC 2617)中找到。

ASP.NET Web Api实现基本认证

关于Http基本认证的优缺点,以及其他相关的只是可参考相关文章。本篇文章主要是使用 ASP.NET Web Api实现Http基本认证。

在这里稍微再啰嗦一句,Http基本认证的请求头是Authorization,响应头是WWW-Authenticate。

认证端实现

在ASP.NET Web Api中实现Http基本认证,需要重写System.Web.Http.AuthorizeAttribute类的两个方法HandleUnauthorizedRequest和OnAuthorization。

        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class HttpBasicAuthenticateAttribute : AuthorizeAttribute
    {

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


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

       /// <summary>
       /// 认证用户
       /// </summary>
        protected virtual bool OnAuthorizeUser(string username, string password, System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                return false;

            return true;
        }


        /// <summary>
        /// 解析Authorization请求头
        /// </summary>
        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]);
        }


        /// <summary>
        /// 发送认证询问请求
        /// </summary>
        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));
        }
    }

    /// <summary>
    /// 表示基本认证用户
    /// </summary>
    public class BasicAuthenticationIdentity : GenericIdentity
    {
        public BasicAuthenticationIdentity(string name, string password)
            : base(name, "Basic")
        {
            this.Password = password;
        }

        public string Password { get; set; }
    }

使用的时候,在Controller上或者Action上加上[HttpBasicAuthenticate],如下图所示:

这样再通过浏览器访问/api/Test的时候就会提示输入用户名和密码

客户端实现

api都是由其他程序调用的,这样就需要手动添加Authorization请求头。如果是通过jquery调用的话,请查找如何添加header以及js如何编码base64的相关知识,这里演示C#的调用。

 static void Main(string[] args)
        {
            Task.WaitAll(CallWebApi());
        }


        static async Task CallWebApi()
        {
            var client = new HttpClient();
            var user = string.Format("{0}:{1}", "u", "p");
            var auth = string.Format("Basic {0}", Convert.ToBase64String(Encoding.Default.GetBytes(user)));
            client.DefaultRequestHeaders.Add("Authorization", auth);

            var requestUri = "http://localhost:4811/api/Test/";

            var response = await client.GetStringAsync(requestUri);

            Console.WriteLine(response);
        }

demo地址:https://github.com/mingceng/http-basic-authenticate-demo

退出移动版