美文网首页
个人网站开发(二) 登陆注册

个人网站开发(二) 登陆注册

作者: RageLy | 来源:发表于2019-02-25 20:46 被阅读0次

    功能说明

    网站通过登录来区分当前访问的用户是否能否访问页面和操作数据。而注册则是登录的前提。


    数据库方面

    首先是使用UserInf表来存储用户的信息,表结构如下

    字段名称 字段类型 字段说明
    UserId int 用户的唯一ID
    AccountName nvarchar(20) 账户名称
    NickName nvarchar(20) 昵称
    UserKinds nvarchar(10) 用户类别
    UserPwd varchar(255) 用户密码(使用MD5存储)
    UserPhone char(11) 用户电话
    UserRegionId varchar(20) 用户地区ID
    UserState nvarchar(10) 用户状态
    UserCreateTime datetime 用户创建时间
    UserSex bit 用户性别
    UserEmail nvarchar(100) 用户邮箱
    UserPhotoId nvarchar(255) 用户头像索引(指向头像文件)

    用户登录成功后会获取到一个授权ID。使用AuthorizationLoginRec表来记录

    字段名称 字段类型 字段说明
    UserId int 这个记录是属于哪一个用户的
    AuthorizationId guid 授权ID
    CreateTime Datetime 授权的开始时间
    EndTime Datetime 授权的终止时间
    States bit 授权状态

    程序逻辑设计

    • 登录流程

      1. 在登录界面输入用户名和密码,前端对用户输入的密码使用JS进行MD5加密后与用户名一起传输到后端,后端根据用户名和密码判断用户是否存在、用户的状态是否正常
      • 验证失败:返回相应的错误提示给前端界面。
      • 验证通过:在AuthorizationLoginRec查询相同UserId的记录,如果存在Statestrue的记录,将其States设置falseEndTime设置为当前时间,然后在AuthorizationLoginRec中新增一条记录,将记录中AuthorizationId值赋值到User对象中。将登录成功返回给前端,再执行相关的跳转逻辑。
    • 注册流程
      用户在注册界面输入相应的信息后,传入到后台进行校验(密码同样使用JS进行MD5加密后的)。如果校验通过则执行登录成功的操作,将用户信息和授权ID赋值到User对象中。返回前端页面注册成功,执行跳转。

    • PS
      相应的操作都是要加上权限校验的,即检查系统目前是否允许登录和注册。关于权限校验后面会讲到。

    前端页面设计

    • 登录页面
      使用的是layui提供的默认登录样式,后面自己前端技能熟练后再来自定义修改,前端的代码可以通过在浏览器查看,就不贴出来了。
    • 注册界面
      同样使用的是layui提供的默认注册样式。

    难点

    • 验证码
      我这里验证码的思路是后台生成图片和对应的字符串,图片在前端进行展示。用户根据图片输入字符后传给后端进行正确性校验。这样的好处是正确的验证码前端是不会存储的,有利于安全性(当然现在使用图像识别的还没有办法,只能不断加大字符的模糊程度,但是这样又会破坏用户的登录体验),坏处就是每次验证码的检查都是要传递给后端的,增加的网络的访问负担。
      1. 生成验证码的工具类
    namespace BLL
    {
        /// <summary>
        /// 生成验证码的类
        /// </summary>
        public class ValidateCode
        {
            public ValidateCode()
            {
            }
            /// <summary>
            /// 验证码的最大长度
            /// </summary>
            public int MaxLength
            {
                get { return 10; }
            }
            /// <summary>
            /// 验证码的最小长度
            /// </summary>
            public int MinLength
            {
                get { return 1; }
            }
            /// <summary>
            /// 生成验证码
            /// </summary>
            /// <param name="length">指定验证码的长度</param>
            /// <returns></returns>
            public string CreateValidateCode(int length)
            {
                int[] randMembers = new int[length];
                int[] validateNums = new int[length];
                string validateNumberStr = "";
                //生成起始序列值
                int seekSeek = unchecked((int)DateTime.Now.Ticks);
                Random seekRand = new Random(seekSeek);
                int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - length * 10000);
                int[] seeks = new int[length];
                for (int i = 0; i < length; i++)
                {
                    beginSeek += 10000;
                    seeks[i] = beginSeek;
                }
                //生成随机数字
                for (int i = 0; i < length; i++)
                {
                    Random rand = new Random(seeks[i]);
                    int pownum = 1 * (int)Math.Pow(10, length);
                    randMembers[i] = rand.Next(pownum, Int32.MaxValue);
                }
                //抽取随机数字
                for (int i = 0; i < length; i++)
                {
                    string numStr = randMembers[i].ToString();
                    int numLength = numStr.Length;
                    Random rand = new Random();
                    int numPosition = rand.Next(0, numLength - 1);
                    validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1));
                }
                //生成验证码
                for (int i = 0; i < length; i++)
                {
                    validateNumberStr += validateNums[i].ToString();
                }
                return validateNumberStr;
            }
    
            /// <summary>
            /// 得到验证码图片的长度
            /// </summary>
            /// <param name="validateNumLength">验证码的长度</param>
            /// <returns></returns>
            public static int GetImageWidth(int validateNumLength)
            {
                return (int)(validateNumLength * 12.0);
            }
            /// <summary>
            /// 得到验证码的高度
            /// </summary>
            /// <returns></returns>
            public static double GetImageHeight()
            {
                return 22.5;
            }
            /// <summary>
            /// 创建验证码的图片
            /// </summary>
            /// <param name="containsPage">要输出到的page对象</param>
            /// <param name="validateNum">验证码</param>
            public byte[] CreateValidateGraphic(string validateCode)
            {
               // Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 38);
                Bitmap image = new Bitmap(148, 38);
                Graphics g = Graphics.FromImage(image);
                try
                {
                    //生成随机生成器
                    Random random = new Random();
                    //清空图片背景色
                    g.Clear(Color.White);
                    //画图片的干扰线
                    for (int i = 0; i < 25; i++)
                    {
                        int x1 = random.Next(image.Width);
                        int x2 = random.Next(image.Width);
                        int y1 = random.Next(image.Height);
                        int y2 = random.Next(image.Height);
                        g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                    }
                    Font font = new Font("Arial", 25, (FontStyle.Bold | FontStyle.Italic));
                    LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
                     Color.Blue, Color.DarkRed, 1.2f, true);
                    g.DrawString(validateCode, font, brush, 13, 2);
                    //画图片的前景干扰点
                    for (int i = 0; i < 100; i++)
                    {
                        int x = random.Next(image.Width);
                        int y = random.Next(image.Height);
                        image.SetPixel(x, y, Color.FromArgb(random.Next()));
                    }
                    //画图片的边框线
                    g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
                    //保存图片数据
                    MemoryStream stream = new MemoryStream();
                    image.Save(stream, ImageFormat.Jpeg);
                    //输出图片流
                    return stream.ToArray();
                }
                finally
                {
                    g.Dispose();
                    image.Dispose();
                }
            }
        }
    }
    
    1. 后端控制器中调用
            /// <summary>
            /// 获取 登陆验证码 接口
            /// </summary>
            /// <returns>验证码图片流</returns>
            public ActionResult GetValidateCode()
            {
                ValidateCode vCode = new ValidateCode();
                string code = vCode.CreateValidateCode(5);
                TempData["ValidateCode"] = code;
                //记录当前验证码生成的时间
                TempData["ValidateDate"] = DateTime.Now;
                byte[] bytes = vCode.CreateValidateGraphic(code);
                return File(bytes, @"image/jpeg");
            }
    
    • 前端进行MD5加密

    总结

    注册、登录功能是网站必备的基础功能,我这里只是单纯的讲解了思路。登录还要对重复登录进行限制,防止爆破登录。注册时要使用手机验证码或者邮箱验证码的方式等等。这个随着我学习的进一步升入,会给大家再带来我新的想法。

    谢谢阅读!

    相关文章

      网友评论

          本文标题:个人网站开发(二) 登陆注册

          本文链接:https://www.haomeiwen.com/subject/gmxnyqtx.html