• 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 (16)源码分享二:登录功能以及UI、数据库、仓储源码分享


    索引

      

    【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 目录索引

      

    前言

      

      前面还没有下载到UI和数据库的,这里再次给大家提供一下:百度网盘  提取码:fuuv ,UI是参照H+,但是H+是收费授权的(¥998RMB),价格有点贵,所以 我们的 UI 跟H+ 虽然是一个风格,但是大家可以看到,CSS基本用的都是Bootstrap,JS 基本都是 最新的开源插件和自己重写的,不存在版权问题。

      我们前一章已经重写了我们的仓储类,文章中接口都已列出,实现类也说的很明白,引入 uow 后,大家修改一下原先的提交,就可以。但是很多朋友 总感觉 不给你文件 是因为 有些东西没有放给你,那么 就再次给大家 下载一下 我的仓储,大家可以对比一下,是不是博客中故意少些东西。修改后的仓储:百度网盘 提取码:qw64 

    其实,只是想让大家自己动手一下,修改方法很简单,就是把我们之前的方法加上个条件: bool IsCommit=true,当我们只进行一项操作的时候,默认直接提交,当我们进行多项操作的时候,可以传入false,不提交,然后通过uow 统一提交。大家可以看一下,使用的例子:

      

     

    卖源码?

      很多朋友都在牢骚,说博主终于还是商业化了...

      首先呢,到目前为止,我没有卖一套源码,如果你在我们的交流群里,你可以问问大家,很多私聊我买源码的朋友,我都是跟他们说先按照博客园的文章自己做,学会才是目的,单纯的源代码是没有任何意义的,博客园贴出的源码跟我项目中源码的唯一区别就是,我项目中的源码没有注释,实在不行再来找我。

      第二呢,有些源码出售网站惊现 果冻博客源码... 这让我很吃惊,首先是受宠若惊,巧合的是,有个源码网站是我朋友的,要不是他发给我我还真不知道,我是不反对这种行为的,你学会了就是你的,卖或不卖是你的事,但是扒下来的代码,都没有经过测试,这么多错误,都跑不起来,就拿来出售,是很不地道的。

      第三呢,我上面说过了,博客园贴出的源码 跟我源码的唯一区别就是,我项目中源码是没有这么多注释的。如果单纯是分享源代码,大可以放到GitHub上,难道一步一步贴出源代码不就分享源码,只有把完整的打个包发给每个人才叫分享源码吗?那博客园的意义是?博客园不是GitHub,两个站的目的是不一样的。对于同样是新手的我来说,github上的纯粹的源代码,如果ReadMe 写的不详细,是很难看懂的,更不用说理解运用了,如果一篇一篇文章,一步一步解释,一条一条注释,然后贴出总体的,都不能理解的话,直接一个完整的源码就能看懂吗?

      伤不起。。。

    登录

      该正事了

      登录控制器 /Areas/SysManage/AccountController,一共有一个视图,两个方法:登录页面、登录验证、验证码

      

      

      首先,我们这个控制器跟区域里其它控制器的一个区别就是,我们没有继承 BaseController,我们可以看下我们的 BaseController 都干了些什么:

      ① 公用变量:主要就是用于试图页传递一些公用变量,例如:查询关键字、分页页码、分页条数等。

      ② 用户对象:网站后台的管理员,我们首先从Session中获取用户,如果Session 失效,那么我们从Cookies中获取用户信息,模拟登录重新赋值 Session 并获取用户,如果Cookies也失效,那么重新登录。

      ③ 邮箱域名:这个是内部邮件用的,我们这里不用。

      ④ 登录验证

      ⑤ log4net日志封装方法

      ⑥ 输出消息

      ⑦ 模块权限验证:我们对每一个模块都有独立的权限,并且监控Action和Method,在前面我们已经完成了对模块权限的初始化和自定义权限扩展,这里我们就需要验证当前用户,对此模块的Action 是否有相应的操作权限(例如:添加、修改、删除、列表以及自定义的诸如 审核、打印、下载等),并且输出权限到视图,同时在视图页对没有相应权限的按钮Remove掉。通俗的讲,就是我们Remove掉视图页中没有权限的按钮,并且监控后台Action的操作,所以即便你自己添加上相应的按钮和方法,提交到后台时也不会通过验证。

      

      通过上面详细的解释,我们可以发现,登录页是不需要这些的,但是后台操作的其它控制器都需要,所以它们都继承了BaseController 但是,登录控制器不需要。

      我们再回头看我们的AccountController:

       Index 这个没什么可解释的,就是登陆页面,我们只是执行了移除Session和Cookies操作。

      我们来看下登录验证方法:

      首先,我们是要验证验证码。(不区分大小写)if (!string.IsNullOrEmpty(code) && code.ToLower() == Session["gif"].ToString().ToLower())

      然后,我们通过用户输入的账号和密码验证用户,这里,我们通过匹配账号和密码返回用户的实体类 var users = UserManage.UserLogin(item.ACCOUNT.Trim(), item.PASSWORD.Trim());

      值得注意的是:因为我们用的加密算法是动态密钥的,所以对相同的字符串每次加密后的密文都是不一样的,因此我们不能通过对用户输入的密码进行加密后与数据匹配,而是通过账号取出密码,对密码进行解密与用户输入匹配的方式验证:

      

      

      如果返回正常,我们首先还要验证用户是否被禁止登录

      

      

      如果这一步验证也通过,我们通过 var acconut = this.UserManage.GetAccountByUser(users); 获取ViewModel:Account 类

      

     1 public class Account
     2     {
     3         #region Attribute
     4         /// <summary>
     5         /// 主键
     6         /// </summary>
     7         public int Id { get; set; }
     8         /// <summary>
     9         /// 姓名
    10         /// </summary>
    11         public string Name { get; set; }
    12         /// <summary>
    13         /// 登录的用户名
    14         /// </summary>
    15         public string LogName { get; set; }
    16         /// <summary>
    17         /// 姓名拼音
    18         /// </summary>
    19         public string PinYin { get; set; }
    20         /// <summary>
    21         /// 登录密码
    22         /// </summary>
    23         public string PassWord { get; set; }
    24         /// <summary>
    25         /// 是否管理员
    26         /// </summary>
    27         public bool IsAdmin { get; set; }
    28         /// <summary>
    29         /// 用户头像
    30         /// </summary>
    31         public string Face_Img { get; set; }
    32         /// <summary>
    33         /// 部门职务
    34         /// </summary>
    35 
    36         public string Levels { get; set; }
    37         /// <summary>
    38         /// 用户所属系统Id
    39         /// </summary>
    40         public List<string> System_Id { get; set; }
    41         /// <summary>
    42         /// 用户主部门
    43         /// </summary>
    44         public Domain.SYS_DEPARTMENT DptInfo { get; set; }
    45         /// <summary>
    46         /// 权限集合
    47         /// </summary>
    48         public List<Domain.SYS_PERMISSION> Permissions { get; set; }
    49         /// <summary>
    50         /// 角色的集合
    51         /// </summary>
    52         public List<Domain.SYS_ROLE> Roles { get; set; }
    53         /// <summary>
    54         /// 用户岗位集合
    55         /// </summary>
    56         public List<Domain.SYS_POST_USER> PostUser { get; set; }
    57         /// <summary>
    58         /// 用户可操作的模块集合
    59         /// </summary>
    60         public List<Domain.SYS_MODULE> Modules { get; set; }
    61         #endregion
    62     }

      这个类里面包含了用户的基本信息和可操作的系统、模块以及相应的权限信息。

       下一步,我们先来验证一下,用户可操作的系统(这里起名有些误导了,应该叫Systems,System_Id给人的印象是系统ID,而不是系统集合): if (acconut.System_Id.Count > 0)

      

    单点登录

      如果可操作系统验证通过,我们检测一下配置文件是否开启了单点登录:单点登录的实现方式其实很简单,这里大体跟大家说一下思路

      首先,我们有个用户在线状态表 UserOnlie

      

      当我们创建用户的时候,这里也会创建一个 一对一 的用户在线状态记录。

      我们在最外层的后台主页面中,有个 SignalR-Hubs ,也是与内部聊天室一体的,当用户登录后或重新连接时,我们便更新用户的在线状态:

      

      当用户离线时,我们更新用户的在线状态为离线:

      

      通过这个简单的方式,很简陋的实现单用户登录模式。

      OK,这样基本的步骤就算完成了,如果用户不在线或没有开启单用户登录,那么我们记录Session和Cookies,如果开启了单用户模式,并且用户已在线,那么我们登录失败,提示当前用户,用户已登录

      json.Msg = "当前用户已登录,系统不允许重复登录!登录IP:" + UserOnline.UserIP;

      这个Login方法大家可以修改一些串行的方法为异步并行,提高效率。登录页的UI 在之前的文章以及本文顶部 已经给大家分享,源码 在前面的文章中也有,但是没有加入单点登录,这个是后来加上的,这里再给大家贴一下完整的登录控制器:

      

      1 using Common;
      2 using Service.IService;
      3 using System;
      4 using System.Collections.Generic;
      5 using System.Linq;
      6 using System.Web;
      7 using System.Web.Mvc;
      8 
      9 namespace WebPage.Areas.SysManage.Controllers
     10 {
     11     public class AccountController : Controller
     12     {
     13         #region 声明容器
     14         /// <summary>
     15         /// 用户管理
     16         /// add yuangang by 2016-05-16
     17         /// </summary>
     18         IUserManage UserManage { get; set; }
     19         /// <summary>
     20         /// 用户在线管理
     21         /// </summary>
     22         IUserOnlineManage UserOnlineManage { get; set; }
     23         /// <summary>
     24         /// 日志记录
     25         /// </summary>
     26         log4net.Ext.IExtLog log = log4net.Ext.ExtLogManager.GetLogger("dblog");
     27         #endregion
     28 
     29         #region 基本视图
     30         public ActionResult Index()
     31         {
     32             //移除Session
     33             SessionHelper.Remove("CurrentUser");
     34             CookieHelper.ClearCookie("cookie_rememberme");   
     35             return View();
     36         }
     37         /// <summary>
     38         /// 登录验证
     39         /// add yuangang by 2016-05-16
     40         /// </summary>
     41         [ValidateAntiForgeryToken]
     42         public ActionResult Login(Domain.SYS_USER item)
     43         {
     44             var json = new JsonHelper() { Msg = "登录成功", Status = "n" };
     45             try
     46             {
     47                 //获取表单验证码
     48                 var code = Request.Form["code"];
     49                 if (Session["gif"] != null)
     50                 {
     51                     //判断用户输入的验证码是否正确
     52                     if (!string.IsNullOrEmpty(code) && code.ToLower() == Session["gif"].ToString().ToLower())
     53                     {
     54                         //调用登录验证接口 返回用户实体类
     55                         var users = UserManage.UserLogin(item.ACCOUNT.Trim(), item.PASSWORD.Trim());
     56                         if (users != null)
     57                         {
     58                             //是否锁定
     59                             if (users.ISCANLOGIN)
     60                             {
     61                                 json.Msg = "用户已锁定,禁止登录,请联系管理员进行解锁";
     62                                 log.Warn(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
     63                                 return Json(json);
     64                             }
     65 
     66                             var acconut = this.UserManage.GetAccountByUser(users);
     67 
     68                             //系统访问正常
     69                             if (acconut.System_Id.Count > 0)
     70                             {
     71                                 //是否启用单用户登录
     72                                 if (System.Configuration.ConfigurationManager.AppSettings["IsSingleLogin"] == "True" )
     73                                 {
     74                                     var UserOnline = UserOnlineManage.LoadListAll(p => p.FK_UserId == users.ID).FirstOrDefault();
     75                                     if(UserOnline!=null && UserOnline.IsOnline)
     76                                     {
     77                                         json.Msg = "当前用户已登录,系统不允许重复登录!登录IP:" + UserOnline.UserIP;
     78                                         log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "重复登录:" + json.Msg);
     79                                     }
     80                                     else
     81                                     {
     82                                         //写入Session 当前登录用户
     83                                         SessionHelper.SetSession("CurrentUser", acconut);
     84 
     85                                         //记录用户信息到Cookies
     86                                         string cookievalue = "{"id":"" + acconut.Id + "","username":"" + acconut.LogName +
     87                                                              "","password":"" + acconut.PassWord + "","ToKen":"" +
     88                                                              Session.SessionID + ""}";
     89                                         CookieHelper.SetCookie("cookie_rememberme", new Common.CryptHelper.AESCrypt().Encrypt(cookievalue),
     90                                             null);
     91 
     92                                         json.Status = "y";
     93                                         json.ReUrl = "/Sys/Home/Index";
     94                                         log.Info(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
     95                                     }
     96                                 }
     97                                 else
     98                                 {
     99                                     //写入Session 当前登录用户
    100                                     SessionHelper.SetSession("CurrentUser", acconut);
    101 
    102                                     //记录用户信息到Cookies
    103                                     string cookievalue = "{"id":"" + acconut.Id + "","username":"" + acconut.LogName +
    104                                                          "","password":"" + acconut.PassWord + "","ToKen":"" +
    105                                                          Session.SessionID + ""}";
    106                                     CookieHelper.SetCookie("cookie_rememberme", new Common.CryptHelper.AESCrypt().Encrypt(cookievalue),
    107                                         null);
    108 
    109                                     json.Status = "y";
    110                                     json.ReUrl = "/Sys/Home/Index";
    111                                     log.Info(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
    112                                 }
    113                             }
    114                             else
    115                             {
    116                                 json.Msg = "站点来源不可信,系统拒绝登录";
    117                                 log.Warn(Utils.GetIP(), "其他系统访问者", "", "Login", "其他系统登录失败,原因:系统验证错误,系统拒绝登录");
    118                             }
    119 
    120                         }
    121                         else
    122                         {
    123                             json.Msg = "用户名或密码不正确";
    124                             log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
    125                         }
    126                     }
    127                     else
    128                     {
    129                         json.Msg = "验证码不正确";
    130                         log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
    131                     }                    
    132                 }
    133                 else
    134                 {
    135                     json.Msg = "验证码已过期,请刷新验证码";
    136                     log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
    137                 }              
    138             }
    139             catch (Exception e)
    140             {
    141                 json.Msg = e.Message;
    142                 log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
    143             }
    144             return Json(json, JsonRequestBehavior.AllowGet);
    145         }
    146         #endregion
    147 
    148         #region 帮助方法
    149         /// <summary>
    150         /// 验证码
    151         /// </summary>
    152         public FileContentResult ValidateCode()
    153         {
    154             string code = "";
    155             System.IO.MemoryStream ms = new Models.verify_code().Create(out code);
    156             Session["gif"] = code;//验证码存储在Session中,供验证。  
    157             Response.ClearContent();//清空输出流 
    158             return File(ms.ToArray(), @"image/png");
    159         }
    160         #endregion
    161     }
    162 }
    View Code
  • 相关阅读:
    读书-《智能时代》-机器智能正在革我们的命
    判断Http服务器是否支持支持断点续传
    最全Html标签Meta介绍
    用PHP整理照片和视频文件
    读书-《癌症.真相:医生也在读》-我所认识的癌症
    scrapy-redis组件配置用例
    Scrapy+seleninu抓取内容同时下载图片几个问题
    无界浏览器Chorme命令行开关
    Scrapy Crawl 运行出错 AttributeError: 'xxxSpider' object has no attribute '_rules' 的问题解决
    福利,OpenCV最新中文版官方教程来了
  • 原文地址:https://www.cnblogs.com/yuangang/p/5789748.html
Copyright © 2020-2023  润新知