欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ASP.NET Web api 身份认证原理解析

程序员文章站 2024-02-29 10:02:58
...

类图:

ASP.NET Web api 身份认证原理解析

TestController.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using System.Web.Security;
using WebApiAuthentication.Core;

namespace WebApiAuthentication.Controllers
{
    [RoutePrefix("Test")]
    public class TestController : ApiController
    {
        [Route("SignIn")]
        [HttpGet]
        public IHttpActionResult SignIn()
        {
            MyFormsAuthenticationTicket ticket = new MyFormsAuthenticationTicket(2, new Random().Next().ToString(), DateTime.Now, DateTime.Now.AddDays(1), true, "admin,张三");
            string encryptStr = MyFormsAuthentication.EncryptDES(JsonConvert.SerializeObject(ticket), "11111111");
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptStr);
            //cookie.HttpOnly = true;
            cookie.Secure = FormsAuthentication.RequireSSL;
            HttpContext context = HttpContext.Current;
            if (context == null)
                throw new InvalidOperationException();
            //  写入Cookie
            context.Response.Cookies.Remove(cookie.Name);
            context.Response.Cookies.Add(cookie);
            return Ok("登陆成功");
        }
        [Route("SignOut")]
        [HttpGet]
        [Authorize]
        public IHttpActionResult SignOut()
        {
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
            cookie.Expires = DateTime.Now.AddDays(-1);
            HttpContext.Current.Response.Cookies.Add(cookie);
            return Ok("退出成功");
        }

        /// <summary>
        /// 测试是否登陆后可以访问
        /// </summary>
        /// <returns></returns>
        [Route("TestSuccess")]
        [HttpGet]
        [Authorize]
        public IHttpActionResult TestSuccess()
        {
            return Ok("访问成功");
        }
        /// <summary>
        /// 测试指定角色
        /// </summary>
        /// <returns></returns>
        [Route("TestRoles")]
        [HttpGet]
        [Authorize(Roles="找刘")]
        public IHttpActionResult TestRoles()
        {
            return Ok("访问成功");
        }
        /// <summary>
        /// 测试指定角色
        /// </summary>
        /// <returns></returns>
        [Route("TestZhangsan")]
        [HttpGet]
        [Authorize(Roles = "张三")]
        public IHttpActionResult TestZhangsan()
        {
            return Ok("访问成功");
        }
    }
}

MyFormsAuthenticationTicket.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace WebApiAuthentication.Core
{
    public class MyFormsAuthenticationTicket
    {
        public MyFormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData)
        {
            this.Version = version;
            this.Name = name;
            this.Expiration = expiration;
            this.IssueDate = issueDate;
            this.IsPersistent = isPersistent;
            this.UserData = userData;
            this.CookiePath = FormsAuthentication.FormsCookiePath;
            DtNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ssss");
        }

        public string CookiePath { get; set; }

        public DateTime Expiration { get; set; }

        public bool Expired { get; set; }

        public bool IsPersistent { get; set; }

        public DateTime IssueDate { get; set; }

        public string Name { get; set; }

        public string UserData { get; set; }

        public int Version { get; set; }

        public string DtNow { get; set; }
    }
}

MyFormsAuthentication.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace WebApiAuthentication.Core
{
    public static class MyFormsAuthentication
    {
        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加***,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
        public static string EncryptDES(string encryptString, string key)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(key);
                byte[] rgbIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            catch
            {
                return encryptString;
            }
        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="key">解***,要求8位</param>
        /// <returns></returns>
        public static string DecryptDES(string decryptString, string key)
        {
            try
            {
                //默认**向量
                byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                byte[] rgbKey = Encoding.UTF8.GetBytes(key);
                byte[] rgbIV = Keys;
                byte[] inputByteArray = Convert.FromBase64String(decryptString);
                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(mStream.ToArray());
            }
            catch
            {
                return decryptString;
            }
        }
    }
}

DecryptHttpMoudle.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace WebApiAuthentication.Core
{
    public class DecryptHttpMoudle : IHttpModule
    {
        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += Context_AuthenticateRequest;
        }
        /// <summary>
        /// 替换HttpContext.Current.User实现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Context_AuthenticateRequest(object sender, EventArgs e)
        {
            var app = sender as HttpApplication;
            if (app == null)
            {
                app.Context.User = null;
                return;
            }
            var cookie = HttpContext.Current.Request.Headers.GetValues("Cookie");
            if (cookie == null)
            {
                app.Context.User = new MyPrincipal("",null);
                return;
            }
            if (cookie.Count() < 1)
            {
                app.Context.User = new MyPrincipal("", null);
                return;
            }
            MyFormsAuthenticationTicket ticket;
            try
            {
                //获取cookie值的另一种方式,特殊符号会被省略
                //var sdd = Request.Headers.GetCookies(FormsAuthentication.FormsCookieName).FirstOrDefault();
                //var value=sdd[FormsAuthentication.FormsCookieName].Value;
                string decryptStr = MyFormsAuthentication.DecryptDES(cookie[0].Substring(cookie[0].IndexOf('=') + 1), "11111111");
                ticket = JsonConvert.DeserializeObject<MyFormsAuthenticationTicket>(decryptStr);
            }
            catch (Exception)
            {
                app.Context.User = new MyPrincipal("", null);
                return;
            }
            if (ticket == null)
            {
                app.Context.User = new MyPrincipal("", null);
                return;
            }
            app.Context.User = new MyPrincipal(ticket.Name,ticket.UserData);
        }
    }
}

MyPrincipal.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;

namespace WebApiAuthentication.Core
{
    public class MyPrincipal : IPrincipal
    {
        private string[] m_roles;
        public MyPrincipal(string name,string roles)
        {
            if (!string.IsNullOrEmpty(roles)) {
                string[] rolesArr = roles.Split(',');
                m_roles = new string[rolesArr.Count()];
                for (int i = 0; i < rolesArr.Count(); i++)
                {
                    m_roles[i] = rolesArr[i];
                }
            }
            _identity = new MyIdentity(name);
        }

        private IIdentity _identity;

        public IIdentity Identity
        {
            get
            {
                return _identity;
            }
        }
        public bool IsInRole(string role)
        {
            if ((role == null) || (this.m_roles == null))
            {
                return false;
            }
            for (int i = 0; i < this.m_roles.Length; i++)
            {
                if ((this.m_roles[i] != null) && (string.Compare(this.m_roles[i], role, StringComparison.OrdinalIgnoreCase) == 0))
                {
                    return true;
                }
            }
            return false;
        }

    }
}

MyIdentity.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;

namespace WebApiAuthentication.Core
{
    public class MyIdentity : IIdentity
    {
        public MyIdentity(string name) {
            this.m_name = name;
            this.m_type = "";
        }
        private string m_type;
        private string m_name;
        public  string Name
        {
            get
            {
                return this.m_name;
            }
        }
        public bool IsAuthenticated
        {
            get
            {
                return !this.m_name.Equals("");
            }
        }
        public string AuthenticationType
        {
            get
            {
                return this.m_type;
            }
        }

    }
}

Web.config

<system.webServer>
    ...
    <!--配置文件里注册的HttpModules-->
    <modules>
      <add name="DecryptHttpMoudle" type="WebApiAuthentication.Core.DecryptHttpMoudle"/>
    </modules>
  </system.webServer>

运行结果如图:

ASP.NET Web api 身份认证原理解析


ASP.NET Web api 身份认证原理解析


ASP.NET Web api 身份认证原理解析


ASP.NET Web api 身份认证原理解析


ASP.NET Web api 身份认证原理解析