快速开发框架登录cookie设置机制

快速开发框架登录cookie设置机制,​登录cookie令牌机制讲解,很高深哦!

前言

登录cookie令牌机制讲解,包含cookie、过滤器、权限、用户等相关。相关类:AuthenticationUtils.cs、TicketUserData.cs、CustomAuthorizeAttribute.cs、UserAuthorizeAttribute.cs和AccountController.cs,如下图:

快速开发框架cookie

机制讲解

先看cookie

AuthenticationUtils.cs的SetAuthCookie函数中,代码如下,都有相关的文字注释说明:

            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                version: 1, // 票证的版本号。
                name: user.LoginAccount, // 与票证关联的用户名。
                issueDate: dt_now, // 票证发出时的本地日期和时间。
                expiration: dt_expires, // 票证过期时的本地日期和时间。
                isPersistent: createPersistentCookie, // 如果票证将存储在持久性 Cookie 中(跨浏览器会话保存),则为 true;否则为 false。
                userData: userData // 存储在票证中的用户特定的数据。
            );
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
            cookie.Value = FormsAuthentication.Encrypt(ticket);
            cookie.HttpOnly = true;
            cookie.Domain = FormsAuthentication.CookieDomain;

            if (ticket.IsPersistent)
                cookie.Expires = dt_expires;

            HttpContext.Current.Response.Cookies.Add(cookie);

插入一张图:

快速开发框架cookie组件

TicketUserData ticketUserData = new TicketUserData(user, funcs.ToArray());

在该函数中还有上面的一段代码,对的,这就是cookie票证数据模型,具体主要代码如下:

    public class TicketUserData
    {
        const char _userData_Split = '\n';

        public int UserID { get; private set; }

        public string LoginAccount { get; private set; }
        public string UserName { get; private set; }
        /// <summary>
        /// true启用,false禁用
        /// </summary>
        public bool IsEnabled { get; private set; }
        public string LoginId { get; set; }
        /// <summary>
        /// 业务相关。。。。。。
        /// </summary>
        public int? CSXTLoginWay { get; set; }
        /// <summary>
        /// 添加人
        /// </summary>
        public string CreateBy { get; set; }
        /// <summary>
        /// 添加时间
        /// </summary>
        public DateTime CreateAt { get; set; }
        /// true为管理员
        /// </summary>
        public bool IsAdministrator { get; private set; }
        public string[] Roles { get; set; }
        public TicketUserData(SystemUser user, string[] roles)
        {
             this.UserID = user.Id;
            this.LoginAccount = user.LoginAccount;
            this.UserName = user.UserName;
            this.IsEnabled = user.IsEnabled;
            this.LoginId =user.LoginId;
            this.CreateAt = user.CreateAt;
            this.CreateBy = user.CreateBy;
            this.CSXTLoginWay = user.CSXTLoginWay;
            this.Email = user.Email;
            this.IP = user.IP;
            this.ParentAccount = user.ParentAccount;
            this.ParentId = user.ParentId;
            this.ProgramID = user.ProgramID;
            this.SchemID = user.SchemID;
            this.Telephone = user.Telephone;
            this.UserType = user.UserType;
            this.IsAdministrator = user.IsAdministrator;
            this.Roles = roles;
        }
        public TicketUserData(string[] roles)
        {
            //this.UserID = user.Id;
            //this.LoginAccount = user.LoginAccount;
            //this.UserName = user.UserName;
            //this.IsEnabled = user.IsEnabled;
            //this.LoginId =user.LoginId;
            //this.CreateAt = user.CreateAt;
            //this.CreateBy = user.CreateBy;
            //this.CSXTLoginWay = user.CSXTLoginWay;
            //this.Email = user.Email;
            //this.IP = user.IP;
            //this.ParentAccount = user.ParentAccount;
            //this.ParentId = user.ParentId;
            //this.ProgramID = user.ProgramID;
            //this.SchemID = user.SchemID;
            //this.Telephone = user.Telephone;
            //this.UserType = user.UserType;
            //this.IsAdministrator = user.IsAdministrator;
            this.Roles = roles;
        }

        /// <summary>
        /// 创建存储于HttpCookie中的用户数据。默认返回用户的Operation清单、中文名、部门名称等数据
        /// </summary>
        /// <param name="ticket"></param>
        /// <returns></returns>
        internal string CreateLoginUserData()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(this.UserID).Append(_userData_Split)   // UserID
                .Append(this.LoginAccount).Append(_userData_Split)      // LoginAccount
                .Append(this.UserName).Append(_userData_Split)          // UserName
                .Append(this.IsEnabled).Append(_userData_Split)         // IsEnabled
                .Append(this.LoginId).Append(_userData_Split)
                .Append(this.CreateAt).Append(_userData_Split)
                .Append(this.CreateBy).Append(_userData_Split)
                .Append(this.CSXTLoginWay).Append(_userData_Split)
                .Append(this.Email).Append(_userData_Split)
                .Append(this.IP).Append(_userData_Split)
                .Append(this.ParentAccount).Append(_userData_Split)
                .Append(this.ParentId).Append(_userData_Split)
                .Append(this.ProgramID).Append(_userData_Split)
                .Append(this.SchemID).Append(_userData_Split)
                .Append(this.Telephone).Append(_userData_Split)
                .Append(this.UserType).Append(_userData_Split)
                .Append(this.IsAdministrator).Append(_userData_Split)   // IsAdministrator
                .Append(string.Join("|", this.Roles));                  // role name array
            return UserDataCryptor.Encrypt(stringBuilder.ToString());
        }

        // 从已序列化的UserData获取基础数据
        internal static TicketUserData ParseFromUserDataString(string userData)
        {
            TicketUserData ticketUserData = null;
            if (!string.IsNullOrEmpty(userData))
            {
                string decryptedText = UserDataCryptor.Decrypt(userData);
                string[] arr = decryptedText.Split(_userData_Split);
                if (arr.Length == 18)
                {
                    if(string.IsNullOrEmpty(arr[7]))
                    {
                        arr[7]="0";
                    }
                    if(string.IsNullOrEmpty(arr[10]))
                    {
                        arr[10]="0";
                    }
                    if(string.IsNullOrEmpty(arr[3]))
                    {
                        arr[3]="True";
                    }
                   
                    if(string.IsNullOrEmpty(arr[10]))
                    {
                        arr[10]="0";
                    }
                    if(string.IsNullOrEmpty(arr[12]))
                    {
                        arr[12]="0";
                    }
                    if(string.IsNullOrEmpty(arr[13]))
                    {
                        arr[13]="0";
                    }
                  SystemUser systemuser=  new SystemUser() {Id=int.Parse(arr[0]),LoginAccount= arr[1], UserName=arr[2], IsEnabled=bool.Parse(arr[3]),
                      LoginId= arr[4], CreateAt=Convert.ToDateTime(arr[5]),CreateBy= arr[6], CSXTLoginWay=int.Parse(arr[7]),Email= arr[8], IP=arr[9],ParentAccount= arr[10], ParentId=int.Parse(arr[11]),
                    ProgramID=int.Parse( arr[12]), SchemID=int.Parse(arr[13]),Telephone= arr[14], UserType=arr[15],IsAdministrator= bool.Parse(arr[16])};
                    ticketUserData = new TicketUserData(systemuser, arr[17].Split(new char[] { '|' }));
                }
            }
            return ticketUserData;
        }

        class UserDataCryptor
        {
            //static byte[] KEY = { 0x4F, 0x41, 0x43, 0x4F, 0x4D, 0x4D, 0x4F, 0x4E };
            //static byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

            const string sKey = "NUPR";

            /// <summary>
            /// DES加密(32位)
            /// </summary>
            /// <param name="pToEncrypt">加密数据</param>
            /// <param name="sKey">密钥(最多4个字符)</param>
            /// <returns>加密后的数据</returns>
            internal static string Encrypt(string pToEncrypt)
            {
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] inputByteArray = Encoding.Unicode.GetBytes(pToEncrypt);
                try
                {
                    des.Key = Encoding.Unicode.GetBytes(sKey);
                    des.IV = Encoding.Unicode.GetBytes(sKey);
                    MemoryStream ms = new MemoryStream();
                    CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    StringBuilder ret = new StringBuilder();
                    foreach (byte b in ms.ToArray())
                    {
                        ret.AppendFormat("{0:X2}", b);
                    }

                    return ret.ToString();
                }
                catch
                {
                    return string.Empty;
                }
            }

            /// <summary>
            /// DES解密(32位)
            /// </summary>
            /// <param name="pToDecrypt">解密数据</param>
            /// <param name="sKey">密钥(最多个字符)</param>
            /// <returns>解密后的数据</returns>
            internal static string Decrypt(string pToDecrypt)
            {
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
                for (int x = 0; x < pToDecrypt.Length / 2; x++)
                {
                    int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
                    inputByteArray[x] = (byte)i;
                }
                des.Key = Encoding.Unicode.GetBytes(sKey);
                des.IV = Encoding.Unicode.GetBytes(sKey);
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                StringBuilder ret = new StringBuilder();

                return System.Text.Encoding.Unicode.GetString(ms.ToArray());
            }
        }
    }

快速开发框架cookie相关主要讲解在上面了。

权限关联讲解

权限相关主要是两个过滤器:CustomAuthorizeAttribute.cs和UserAuthorizeAttribute.cs。请看这两个类的关键代码:

  UserAuthorizeAttribute.cs:          
            var cookie = AuthenticationUtils.GetTicketUserData();
            var action = filterContext.ActionDescriptor.ActionName;
            var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            if (controller == "Home")   //首页模块不在做权限处理
            {
                base.OnActionExecuting(filterContext);
                return;
            }
         
            if (cookie == null)
            {
                  filterContext.Result = new RedirectResult("~/Logout");
                //filterContext.Result = new ContentResult { Content = @"登录超时,请退出后重新登录!" };
            }
            else
            {
                IUserManageService userManageService =ObjectContainerFactory.CurrentContainer.Resolve<IUserManageService>();
                var user =userManageService.GetUser(cookie.UserID);
                if (user.LoginId != cookie.LoginId)
                {
                    //FormsAuthentication.SignOut();
                    filterContext.Result = new ContentResult { Content = @"该用户已在别处登录,请退出重新登录!" };
                }
            }

上端代码中主要是登录超时控制和账号只能一个地方登录的控制,如上汉字部分的提示说明解释。

CustomAuthorizeAttribute.cs

            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                //filterContext.Controller.SetPermissionData(filterContext);
                SystemUser syetemuser = filterContext.Controller.GetCurrentUser();
                if (syetemuser == null)
                {
                    filterContext.Result = new RedirectResult("~/Logout");
                    return;
                }
                
                if (!filterContext.Controller.HasPermission())
                {
                    filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                    filterContext.Result = new ViewResult() { ViewName = "~/Views/Shared/Forbidden.cshtml" };
                    return;
                }
            }

上端代码中主要是权限的控制,如果没有权限则跳转到forbidden页面,如上所示。

更多功能权限控制请参考:Web开发框架功能权限配置说明

结语

快速开发框架cookie机制的讲解, 好像还漏掉了些什么,对了,我们什么时候去调用,该怎么去调用呢?

既然是登录机制的讲解,那肯定是登录的时候去初始化调用,请看AccountController.cs中登录成功后的处理代码,LoginSuccess函数中:

AuthenticationUtils.SetAuthCookie(user, model.RememberMe);
快速开发框架cookie原理图 


标签: Web开发框架开发指南红宝书

网站&系统开发技术学习交流群:463167176

本站文章除注明转载外,均为本站原创或翻译,欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,共创和谐网络环境。
转载请注明:文章转载自:软件开发框架 » 快速开发框架登录cookie设置机制
本文标题:快速开发框架登录cookie设置机制
本文地址:https://www.hocode.com/OrgTec/Plugin/0037.html

相关文章: 软件开发框架业务表单开发流程

电话
电话 18718672256

扫一扫
二维码