ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(9)之系统登录

    前面我们已经做好了一个文章管理功能模块,接下来,我们回头来做登录窗口,登录不仅涉及到登录验证还涉及到登录日志还有缓存时长等。

    对于缓存的相关设置,我们已经写好封装在Bobo.Utilities.dll程序集中,我们只需要引用就好,没有的,请到此处下载

    在实现之前,我们需要先在表现层创建一个Resource文件夹,用于存放我们公共的文件、图片及模板等,然后下载

IPScaner.zip,并加压到Resource文件夹下。

    QQwry.dat 纯真IP数据库收集了包括中国电信、中国网通、长城宽带、网通宽带、聚友宽带等 ISP 的最新准确 IP 地址数据。目前该库不是最新的数据,大家可以到网上下载到该目录下,这在我们做登录日志时可用到。

一、我们在区域BackstageModule下创建Login的控制器和视图:

(1)LoginController.cs控制器

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using IA.Business.SystemBusiness;
using IA.Entity;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace IA.WebApp.Areas.BackstageModule.Controllers
{
    /// <summary>
    /// 后台登录控制器
    /// </summary>
    public class LoginController : Controller
    {
        //
        // GET: /BackstageModule/Login/

        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// 登录 
        /// </summary>
        /// <param name="Account"></param>
        /// <param name="Password"></param>
        /// <param name="Code"></param>
        /// <returns></returns>
        public ActionResult SubmitLogin(string Account, string Password, string Code)
        {
            try
            {
                Code = Md5Helper.CreateMd5(Code.ToLower(), 16);
                if (Session["session_Userloginvcode"].ToString() != Code)
                {
                    return Content(new JsonMessage { Success = false, Code = "-2", Message = "验证码不正确" }.ToString());
                }
                if (string.IsNullOrEmpty(Account) || string.IsNullOrEmpty(Password))
                {
                    return Content(new JsonMessage { Success = false, Code = "-1", Message = "用户名或密码错误!" }.ToString());
                }
                IPScanerHelper objScan = new IPScanerHelper();
                string IPAddress = NetHelper.LANIP;
                objScan.IP = IPAddress;
                objScan.DataPath = Server.MapPath("~/Resource/IPScaner/QQWry.Dat");
                string IPAddressName = objScan.IPLocation();

                int IsOk = new Base_UserBll().UserLogin(Account, Password, IPAddressName, IPAddress);
                string strCode = "-1";
                string Message = "";
                string czMsg = "";
                bool Success = false;
                switch (IsOk)
                {
                    case 1:
                        strCode = "1";
                        Message = "登录成功!";
                        czMsg = "登录成功!";
                        Success = true;
                        break;
                    case 2:
                        strCode = "-1";
                        Message = "登录失败,用户名或密码错误!";
                        czMsg = "密码错误!";
                        Success = false;
                        break;
                    case 3:
                        strCode = "-1";
                        Message = "登录失败,用户名或密码错误!";
                        czMsg = "账号不存在!";
                        Success = false;
                        break;
                }
                Base_SysLogBll.Instance.WriteLog(Account, OperationType.Login, strCode, czMsg + "、IP所在城市:" + IPAddressName);
                return Content(new JsonMessage { Success = Success, Code = strCode, Message = Message }.ToString());
            }
            catch (Exception ex)
            {
                return Content(new JsonMessage { Success = false, Code = "-1", Message = "操作失败:" + ex.Message }.ToString());
            }

        }
        /// <summary>
        /// 验证码
        /// </summary>
        /// <returns></returns>
        public ActionResult VerifyCode()
        {
            int codeW = 80;
            int codeH = 22;
            int fontSize = 16;
            string chkCode = string.Empty;
            //颜色列表,用于验证码、噪线、噪点 
            Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
            //字体列表,用于验证码 
            string[] font = { "Times New Roman", "Verdana", "Arial", "Gungsuh", "Impact" };
            //验证码的字符集,去掉了一些容易混淆的字符 
            char[] character = { '2', '3', '4', '5', '6', '8', '9', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
            Random rnd = new Random();
            //生成验证码字符串 
            for (int i = 0; i < 4; i++)
            {
                chkCode += character[rnd.Next(character.Length)];
            }
            //写入Session、验证码加密
            Session["session_Userloginvcode"] = Md5Helper.MD5(chkCode.ToLower(), 16);
            //创建画布
            Bitmap bmp = new Bitmap(codeW, codeH);
            Graphics g = Graphics.FromImage(bmp);
            g.Clear(Color.White);
            //画噪线 
            for (int i = 0; i < 1; i++)
            {
                int x1 = rnd.Next(codeW);
                int y1 = rnd.Next(codeH);
                int x2 = rnd.Next(codeW);
                int y2 = rnd.Next(codeH);
                Color clr = color[rnd.Next(color.Length)];
                g.DrawLine(new Pen(clr), x1, y1, x2, y2);
            }
            //画验证码字符串 
            for (int i = 0; i < chkCode.Length; i++)
            {
                string fnt = font[rnd.Next(font.Length)];
                Font ft = new Font(fnt, fontSize);
                Color clr = color[rnd.Next(color.Length)];
                g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 18 + 2, (float)0);
            }
            //将验证码图片写入内存流,并将其以 "image/Png" 格式输出 
            MemoryStream ms = new MemoryStream();
            try
            {
                bmp.Save(ms, ImageFormat.Png);
                return File(ms.ToArray(), @"image/Gif");
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                g.Dispose();
                bmp.Dispose();
            }
        }

        /// <summary>
        /// 退出当前登录,清空所有用户cookie
        /// </summary>
        /// <returns></returns>
        public ActionResult LoginOut()
        {
            /*****************************************
             * 采用双cookie登录,则需要释放双cookie
             * 标准cookie记录用户主要信息,附加cookie用于前台
             * 附加cookie可记录自定义的任何信息
             * ***************************************/
            //清空当前登录用户信息
            ManageProvider.Provider.EmptyCurrent();
            ManageProvider.Provider.EmptyCurrent<Base_User>();
            Session.Abandon();  //取消当前会话
            Session.Clear();    //清除当前浏览器所以Session
            return Content("1");
        }
    }
}

(2)Index视图

@{
    ViewBag.Title = "登录";
   
}
<script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script>
<script src="~/Content/Scripts/jquery.form.js"></script>
<script src="~/Content/Scripts/boboui-jshelp.js"></script>
<script src="~/Content/Scripts/validator/boboui-validator.js"></script>
<script src="~/Content/Scripts/layer/layer.js"></script>
<script src="~/Content/Scripts/jQuery.md5.js"></script>
<link href="~/Content/Styles/base.css" rel="stylesheet" />
<link href="~/Content/Styles/main.css" rel="stylesheet" />
<body style="background-color: #4e95e5; " class="font-yahei">
    <div class="mainBox">
        <h1 style="text-align: center; font-weight: bold; font-size:24px; color: #fff; padding-bottom: 25px; letter-spacing: 2px;">枼落NO.1</h1>
        <div class="Dialog-Box BoxS" style="margin: 0 auto; max-width: 500px; max-height: 300px; background-color: #fff; border-radius: 4px; padding: 0;">
            <div class="Dialog-Tit-com" style="position:relative">系统用户登录</div>
            <div class="login-Ico L"><img src="~/Content/Images/slice/users_03.png" width="78" height="76" /> </div>
            <div class="login-box L">
                <form id="form1" action="/BackstageModule/Login/SubmitLogin" method="post" enctype="multipart/form-data" style="margin: 1px">
                    <table class="layer-table-form">
                        <tr>
                            <td><span class="layer-form-tit">用户名:</span><input style="height:30px;border-radius:4px;" type="text" name="Account" class="layer-form-txt" id="Account" datacol="yes" err="用户名" checkexpession="NotNull" /></td>
                        </tr>
                        <tr>
                            <td><span class="layer-form-tit">密 &nbsp;&nbsp;码:</span><input style="height:30px;border-radius:4px;" type="password" name="Password" class="layer-form-txt" id="Password" datacol="yes" err="密码" checkexpession="NotNull" /></td>
                        </tr>
                        <tr>
                            <td>
                                <span class="layer-form-tit">验证码:</span><input type="text" name="Code" style="width: 100px; height: 30px; border-radius: 4px; " class="layer-form-txt" id="Code" datacol="yes" err="验证码" checkexpession="NotNull" />
                                <img id="codeImg" src="/BackstageModule/Login/VerifyCode" data-url="/BackstageModule/Login/VerifyCode" alt="点击切换验证码" onclick="switchCode($(this))" />
                            </td>
                        </tr>
                    </table>
                </form>
            </div>
            <div class="Dialog-sub-com" style="position:relative">
                <input type="button" value="登录" class="Dialog-btn subBtn" onclick="AcceptClick()">
                <input type="button" value="取消" class="Dialog-btn extBtn" onclick="selfClose()">
            </div>
        </div>
    </div>
    <div class="clear" style="position:fixed;bottom:10px;color:#fff;text-align:center;width:100%;">页落素材网 Copyright 2008-2018 All Rights Reserved</div>
</body>

<script type="text/javascript">
    //提交表单
    function AcceptClick() {
        if (!CheckDataValid('#form1', true)) {
            return false;
        }

        var postData = GetWebControls("#form1");
        postData.Password = escape($.md5(postData.Password));
        $.post("/BackstageModule/Login/SubmitLogin?Code=" + $("#Code").val(), postData, function (data) {
            layer.msg(data.Message, { icon: data.Code, time: 1000 }, function () {
                if (data.Code > 0) {
                    selfClose();
                    location.href = "/BackstageModule/ArticleMange/Index";
                }
                else if (data.Code == -2) {
                    $("#Code").val("").focus();
                    switchCode($("#codeImg"));
                }
            });
        }, "json");
    }
    //回车键
    document.onkeydown = function (e) {
        if (!e) e = window.event; //火狐中是 window.event
        if ((e.keyCode || e.which) == 13) {
            AcceptClick();
        }
    }
    //自定义关闭窗口
    function selfClose() {
        var index = parent.layer.getFrameIndex(window.name);
        parent.layer.close(index);
    }
    //切换验证码
    function switchCode(obj) {
        var url = obj.attr("data-url");
        url += "?date=" + new Date().toString();
        obj.attr("src", url);
    }
</script>

    二、在完成登录操作的过程后,我们需要对登录权限的认证,也就是非登录不可访问。

    首先我们需要在表现层中的SystemExtension文件夹中添加LoginAuthorizeAttribute.cs和ManagerPermissionAttribute.cs登录权限类:

    (1)LoginAuthorizeAttribute.cs

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace IA.WebApp.SystemExtension
{
    /// <summary>
    /// 登录权限认证
    /// </summary>
    public class LoginAuthorizeAttribute : AuthorizeAttribute
    {
        //地址参数的绝对路径("~/aaa/vvv")
        private String _LoginUrl = String.Empty;
        //无参构造器
        public LoginAuthorizeAttribute() { }

        /// <summary>
        /// 标记构造器,可传入登陆地址
        /// </summary>
        /// <param name="LoginUrl">地址参数的绝对路径("~/aaa/vvv")</param>
        public LoginAuthorizeAttribute(string LoginUrl)
        {
            this._LoginUrl = LoginUrl;
        }
        /// <summary>
        /// 响应前执行验证,查看当前用户是否有效 
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var areaName = filterContext.RouteData.DataTokens["area"];
            var controllerName = filterContext.RouteData.Values["controller"];
            var action = filterContext.RouteData.Values["Action"];
            var returnUrl = filterContext.RequestContext.HttpContext.Request.Url.ToString();
            if (!StringHelper.IsNullOrEmpty(this._LoginUrl) && this._LoginUrl.IndexOf('?') == -1)
            {
                this._LoginUrl += ("?ReturnUrl=" + StringHelper.Escape(returnUrl));
            }
            if (this._LoginUrl.IndexOf("BackstageModule") != -1)
            {
                if (!ManageProvider.Provider.IsOverdue())
                {
                    filterContext.Result = new RedirectResult(this._LoginUrl);
                }
                else
                {
                    if (ManageProvider.Provider.Current().Code != "System")
                    {
                        filterContext.Result = new RedirectResult(this._LoginUrl);
                    }
                }
            }
            else
            {

                //登录是否过期
                if (!ManageProvider.Provider.IsOverdue())
                {
                    filterContext.Result = new RedirectResult(this._LoginUrl);
                }
                else
                {
                    if (ManageProvider.Provider.Current().Code == "System")
                    {
                        filterContext.Result = new RedirectResult(this._LoginUrl);
                    }
                }
            }
        }
    }
}

    (2)ManagerPermissionAttribute.cs

using Bobo.Utilities;
using Bobo.Utilities.Membership;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace IA.WebApp.SystemExtension
{
    public class ManagerPermissionAttribute : AuthorizeAttribute
    {
        private PermissionMode _CustomMode;
        /// <summary>默认构造</summary>
        /// <param name="Mode">权限认证模式</param>
        public ManagerPermissionAttribute(PermissionMode Mode)
        {
            _CustomMode = Mode;
        }
        /// <summary>权限认证</summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            //登录权限认证
            if (!ManageProvider.Provider.IsOverdue())
            {
                filterContext.Result = new RedirectResult("~/Login/Default");
            }
            //防止被搜索引擎爬虫、网页采集器
            if (!this.PreventCreeper())
            {
                filterContext.Result = new RedirectResult("~/Login/Default");
            }
            //权限拦截是否忽略
            if (_CustomMode == PermissionMode.Ignore)
            {
                return;
            }
            //执行权限认证
            if (!this.ActionAuthorize(filterContext))
            {
                ContentResult Content = new ContentResult();
                Content.Content = "<script type='text/javascript'>top.Loading(false);alert('很抱歉!您的权限不足,访问被拒绝!');</script>";
                filterContext.Result = Content;
            }
        }
        /// <summary>
        /// 执行权限认证
        /// </summary>
        /// <returns></returns>
        private bool ActionAuthorize(AuthorizationContext filterContext)
        {
            if (ManageProvider.Provider.Current().IsSystem && ManageProvider.Provider.Current().CompanyCategory != "SystemUnit")
                return true;
            var areaName = filterContext.RouteData.DataTokens["area"] + "/";            //获取当前区域
            var controllerName = filterContext.RouteData.Values["controller"] + "/";    //获取控制器
            var action = filterContext.RouteData.Values["Action"];                      //获取当前Action
            string requestPath = "/" + areaName + controllerName + action;              //拼接构造完整url
            string ModuleId = DESEncrypt.Decrypt(CookieHelper.GetCookie("ModuleId"));
            //bool Result = Base_ModulePermissionBll.Instance.ActionAuthorize(requestPath.ToLower(), ManageProvider.Provider.Current().ObjectId, ModuleId, ManageProvider.Provider.Current().UserId);
            return true;// Result;
        }
        /// <summary>
        /// CA验证方法
        /// </summary>
        /// <param name="filterContext"></param>
        /// <returns></returns>
        private bool ActionCA(AuthorizationContext filterContext)
        {
            //TODO:如何在过滤器调用CA的前台检测方法返回值(NC)
            if (ManageProvider.Provider.Current().IsSystem && ManageProvider.Provider.Current().CompanyCategory != "SystemUnit")
            {
                return true;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 防止被搜索引擎爬虫、网页采集器
        /// </summary>
        /// <returns></returns>
        private bool PreventCreeper()
        {
            return true;
        }
    }
}

权限认证做好后,我们在需要权限认证的控制器上加上[LoginAuthorize("~/BackstageModule/Login/Index")]这句了,例如文章控制器:

19.png

然后改造公共布局页_LayoutMange.cshtml:

@using Bobo.Utilities.Membership
@using IA.Business
<!DOCTYPE html>
<html>
@*后台公共模块*@
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" media="screen" />
    <link href="~/Content/Styles/main.css" rel="stylesheet" />
    <link href="~/Content/Styles/base.css" rel="stylesheet" />
    <script src="~/Content/Scripts/datepicker/WdatePicker.js"></script>
    <script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script>
    <script src="~/Content/Scripts/jquery.form.js"></script>
    <script src="~/Content/Scripts/boboui-jshelp.js"></script>
    <script src="~/Content/Scripts/validator/boboui-validator.js"></script>
    <script src="~/Content/Scripts/layer/layer.js"></script>
    <script src="~/Content/Scripts/Juicer/juicer.js"></script>
    <script src="~/Content/Scripts/m_pager.js"></script>
</head>
<body class="set_body">
    <div class="w_header font-yahei">
        <div class="header-item">
            <div class="mAuto">
                <div class="L">页落素材网 - 用户管理后台   【当前用户】:@ManageProvider.Provider.Current().UserName</div>
                <div class="R"><a href="javascript:;" id="LoginOut" style="color: #00b7f0;">【退出登录】</a></div>
            </div>
        </div>
        <div class="header-nav clear">
            <div class="mAuto">
                <a href="/" class="logo L"> <img src="~/Content/Images/slice/logoMange.png" /></a>
                <ul class="R nav-item">
                    <li class="L"><a href="/BackstageModule/Article/Index" class="wzgl">网站管理</a></li>
                    <li class="L"><a href="/BackstageModule/TrainSignupInfo/Index" class="hypx">区块链</a></li>
                    <li class="L"><a href="/BackstageModule/MemberManagement/Index" class="hygl">人工智能</a></li>
                    <li class="L"><a href="/">返回首页</a></li>
                </ul>
            </div>
        </div>
    </div>

    @RenderBody()
    <div id="footer">
        <div class="foot-tip w_footer">
            <div class="webPage text-center">
                页落素材网是网页特效下载社区,以提高效率、分享经验的理念,提供高品质实用、简单、易懂的Web页面特效。
            </div>
        </div>
    </div>

    <script type="text/javascript">
        $(function () {
            $("#LoginOut").on("click", function () {
                AjaxJson("/BackstageModule/Login/LoginOut", {}, function (data) {
                    layer.msg("您已退出登录,欢迎再来哦 ^_^", { icon: 6, shade: [0.3, '#000'] }, function () {
                        location.href = "/BackstageModule/Login/Index";
                    });
                });
            });
        })
        //复选框选定事件
        function change(obj) {
            var tr = obj.parentElement.parentElement;
            if (obj.checked) {
                tr.style.backgroundColor = '#e5eaff';
                tr.style.borderColor = '#cacccb';
            } else {
                tr.style.backgroundColor = '#fff';
            }
        }
    </script>
    @RenderSection("scripts", required: false)
</body>
</html>

登录效果图预览

localhost_7096_BackstageModule_login_Index.png

posted @ 2018-11-15 15:27  落日知暮  阅读(386)  评论(0编辑  收藏  举报
作者:boyzi007 出处:http://www.cnblogs.com/boyzi/ QQ:470797533 QQ交流群:364307742 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。