【C#MVC4】菜单管理和访问权限分配(二)

【C#MVC4】菜单管理和访问权限分配(二)

这一篇介绍登录的实现。
上一篇中我们已经将准备工作完成的差不多。我喜欢从后面往前面书写代码,这里就按照我的思维顺序进行编写。

User_Master_Service:(根据用户名和密码查询出User_Master对象,并返回)

namespace Arise.Service
{
    public class User_Master_Service
    {
        public User_Master GetUserMasterByLoginIdAndPassword(string loginId,string password)
        {
            using(AriseEntities ariseEntities = new AriseEntities())
            {
                return ariseEntities.User_Master.Where(um => um.User_Login_Id == loginId && um.User_Password == password).FirstOrDefault();
            }
        }
    }
}

对linq不是很熟悉的朋友,可以简单的了解一下linq之后,再继续阅读,因为接下来用的均是linq操作数据库。至于linq的优点,不再赘述。

User_Master_Manager:(中间层,这里没有太大作用)

namespace Arise.Manager
{
    public class User_Master_Manager
    {
        private User_Master_Service userMasterService = new User_Master_Service();
        public User_Master GetUserMasterByLoginIdAndPassword(string loginId,string password) 
        {
            try 
            {
                return userMasterService.GetUserMasterByLoginIdAndPassword(loginId,password);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
    }
}

底层链接的写完之后,我们又要接触新的东西了。Controller,在.net mvc中,访问方式是由App_Set文件夹下 Route.config的路由规则定义的,在创建时,有一个默认的路径,这里根据我们的需求,将之改为我们的默认加载路径:

   public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Login", action = "LoginPage", id = UrlParameter.Optional }
            );
        }
    }

其中Login代表LoginController,LoginPage表示第一次默认加载的action。
所以我们新建一个名为LoginController的控制器,并在其中添加一个名为LoginPage的方法。

  public class LoginController : Controller
    {
        //
        // GET: /Login/

        public ActionResult LoginPage()
        {
            return View();
        }
    }

这里LoginPage方法表示,返回到一个名为“LoginPage”的视图中。ActionResult,返回视图对象; View(),默认与action名相同的视图名。这样我们需要在View层建立一个名为LoginPage的视图,它仍然要遵守一些规则,那就是必须放在名为“Login”的文件夹下,这个命名规则是根据controller名而来的。
意思就是,在controller里返回的视图必须返回到与该controller命名相同的文件夹下,且视图名与action相同(默认的情况下,这个可以自定义的,但是一般遵循这个命名规则)。

这样我们在视图LoginPage中添加前台代码:

@{
    ViewBag.Title = "Login";
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Shipping Activity Management</title>
    <link href="@Url.Content("~/JS/EasyUI/themes/default/easyui.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/icon.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/demo/demo.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/myicon1.css")" rel="stylesheet" />
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/jquery.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/jquery.easyui.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/Public.js")"></script>
    <script type="text/javascript">
        $(function () {<!-- -->
            $("#loginid").focus();
        });
        document.onkeydown = function (event_e) {<!-- -->
            if (window.event) {
                event_e = window.event;
            }

            var int_keycode = event_e.charCode || event_e.keyCode;
            if (int_keycode == '13') {
                //your handler function,please.
                checkform();
                return false;
            }
        }
        function checkform() {<!-- -->
            var loginid = $("#loginid").val();
            if (loginid == "" || loginid == "Please Entry User Name") {
                alert("Please Entry User Name!");
                return;
            }

            var password = $("#password").val();
            if (password == "") {
                alert("Please Entry Password!");
                return;
            }
            $.ajax({
                url: '/Login/CheckLogin',
                type: 'post',
                dataType: 'json',
                data: {
                    Loginid: loginid, Password: password
                },
                async: false,
                success: function (data) {<!-- -->
                    if (data.result == "0") {
                        alert(data.message);
                        window.location.href = "/Login/LoginPage";
                    } else {
                        window.location.href = "/Admin/Home";
                    }
                }
            });
        }
    </script>
</head>
<body>
    <div style="position: absolute; top: 50%; left: 50%; width: 350px; height: 200px; margin-left: -175px; margin-top: -180px;">

        <div style="float:left;width:100%;height:100%;border:1px solid black;">
            <div style="margin-top: 20px;">
                <h2 style="color: #409192;text-align:center;"> 测试登录</h2>
            </div>
            <div>
                <table style="float:left;margin-left:35px;">
                    <tr>
                        <td>
                            <label style="font-size:14px;">Login Id:</label>
                        </td>
                        <td>
                            <input type="text" id="loginid" name="loginid" value="woshitm" class="easyui-textbox" style="width:200px;" placeholder="User Name" />
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <label style="font-size:14px;">Password:</label>
                        </td>
                        <td>
                            <input type="password" id="password" name="password" value="tangming" class="easyui-textbox" style="width:200px;" placeholder="Password" />
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            <a href="#" class="easyui-linkbutton" onclick="checkform();">Login</a>
                        </td>
                    </tr>
                </table>
            </div>
        </div>

    </div>
</body>

</html>

这里我们使用ajax的方式,去后台校验信息。这个时候我们需要在logincontroller中添加LoginChack方法:

namespace Arise.Web.Controllers
{
    public class LoginController : Controller
    {
        //
        // GET: /Login/

        public ActionResult LoginPage()
        {
            return View();
        }

        public JsonResult CheckLogin() 
        {
            string loginId = Request.Params["LoginId"].ToString().Trim();
            string password = Request.Params["Password"].ToString().Trim();
            User_Master_Manager userMasterManager = new User_Master_Manager();
            User_Master userMaster = userMasterManager.GetUserMasterByLoginIdAndPassword(loginId,password);
            if(userMaster == null)
            {
              return  Utility.ReturnJsonResult("0",UserMessageShow.ErrorPassword);
            }
            if(Session["UserMaster"] != null && ((User_Master)Session["UserMaster"]).User_Master_Id == userMaster.User_Master_Id)
            {
                return Utility.ReturnJsonResult("0", UserMessageShow.ErrorLogin);
            }
            Session["UserMaster"] = userMaster;
            return Utility.ReturnJsonResult("1", "");
        }
    }
}

很简单的一个处理,若存在user,则保存在session中,否则返回错误信息。第二个判断是为防止多用户使用同一个账号同时登录的,但是经过我测试,在同一个浏览器下实现了,但是在两个不同的浏览器并没有任何作用。可能是每个浏览器对session的id保存不一致,并没有深入研究其中的原因,说的可能不太对,但是你可以将登录信息放到application域中,这样即使不在同一浏览器也是可以检测到的,以为application域是所用用户共享的,我只提供这一个思路,并没有实现过,所以可不可行还需要自己去尝试。

关于这里的返回值jsonResult,不做过多的解释,可以去看api,前面工具类对这个返回封装了两个方法,这里使用第二个方法,客户端可以根据第一个参数是否为0或是为1来判断是否登录成功,以及错误信息的展示。

在页面对于登录状态的不同做了两种操作,一种是登录失败,显示错误信息,重新加载登录页面。另一种是登录成功,访问Home页面,但是这样就带来一种隐患,你是如何知道在你跳转的期间,session不会因为(服务器突然挂了等)某些不可知的原因而过期或清除呢?,这样就要求我们在对一些敏感的链接访问时(由于我们是以后台系统做例子,所以每一步都属于敏感访问,若是公司主页一类的无关的链接不用加),需要判断当前用户的session是否存在。但是每一个方法里面都加入这种判断明显是不现实的,代码的重复率太高,这样我们就可以做一个类似于的过滤器的东西,当访问到达controller层时,同一的都先验证session是否存在,不存在,跳回登录页面,存在则可以进入访问的action。这样,每一个controller都去继承一个BaseController,在BaseController中加入校验即可实现。

BaseController:

namespace Arise.Web.Controllers
{
    public class BaseController : Controller
    {
        //
        // GET: /Base/
        protected override void OnException(ExceptionContext filterContext)
        {
            base.OnException(filterContext);
            string errorMessage = LogHelper.RecordError(filterContext.Exception);
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Redirect("/Login/ErrorPage?msg=" + errorMessage);//跳转至错误提示页面
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            if (Session["UserMaster"] == null)
            {
                Response.Redirect("/Login/LoginPage");                
            }
        }

    }
}

第一个方法:重大的异常信息(Error级别)的信息展示。当你的系统执行到这一步,说明你的系统有重大的错误,比如404,500等
第二个方法:OnActionExecuting,表示在Action执行之前执行。

接着上面的登录流程,我们判断session后,进入Home方法,Home返回一个视图,我们进入到视图页面,在Home页面我们想加入一些登录信息的展示,这样我们可以再Home方法中使用ViewBag添加属性。

namespace Arise.Web.Controllers
{
    public class AdminController : BaseController
    {
        //
        // GET: /Admin/

        public ActionResult Home()
        {
            User_Master userMaster = (User_Master)Session["UserMaster"];
            ViewBag.User = userMaster.User_Name;
            ViewBag.Date = DateTime.Now;

            //ViewBag.MenuTreeList; //下一篇菜单管理讲解
            return View();
        }
        public ActionResult Index()
        {
            return View();
        }
    }
}

这一篇我们只做一个登录的例子,因为登录进去之后我们要拉去当前用户的菜单信息,我先讲这一部分注释,等下一篇在展示。再来看Home页面:

@{
    ViewBag.Title = "Home";
}

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Shipping Activity Management</title>
    <link href="@Url.Content("~/JS/EasyUI/themes/default/EliteCSS.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/default/easyui.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/default/CustomStyle.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/icon.css")" rel="stylesheet" />
    <link href="@Url.Content("~/JS/EasyUI/themes/myicon1.css")" rel="stylesheet" />
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/jquery.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/jquery.easyui.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/JS/EasyUI/Public.js")"></script>
</head>

<body class="easyui-layout">
    <div region="north" border="false" style="overflow: hidden; height: 40px; background: #DBEFE0 repeat-x center 50%; line-height: 20px; color: #fff; font-family: Verdana, 微软雅黑,黑体">
        <div style="width:100%;color:black;">
            <div style="width: 280px; float: left; margin: 10px 5px 5px 10px; font-size: medium; color: #15428b">
                菜单管理Demo
            </div>
            <div style="float: right; margin: 12px 5px 5px 10px;">
                <table style="font-size: 12px; font-weight: bold; color: #15428b" cellpadding="0px" cellspacing="0px" width="100%">
                    <tr>
                        <td>
                            Welcome :
                        </td>
                        <td>
                            &nbsp;@ViewBag.User
                        </td>
                        <td style="width:60px;" align="right">
                            Date:
                        </td>
                        <td>
                            @ViewBag.Date
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
    <div region="west" hide="true" split="true" title="菜单" style="width: 180px;" id="west">
        <div id="nav" class="easyui-accordion" fit="true" border="false">
            <ul id="tt" class="easyui-tree" style="margin-top:10px;color:black;font-size:13px;">
               @*@Html.Raw(@ViewBag.MenuTreeList)*@
            </ul>
        </div>
    </div>
    <div region="center" title="主页信息">
        <div id="Maintabs" class="easyui-tabs" fit="true" border="false">
            <div title="Index" style="padding: 10px; overflow: hidden;" id="home" align="center">
                <iframe scrolling="auto" frameborder="0" src="/Admin/Index" style="width: 100%;height: 100%;" align="top"></iframe>
            </div>
        </div>
    </div>
    <div region="south" border="false" style="height: 30px; background: #fff; padding: 10px;">
        <div style="width:330px;margin:auto">
            Copyright © 2016 - 2025 河南理工大学-Arise
        </div>
    </div>
</body>

</html>

默认的一个初始tab页:

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>主页</h2>

至此,登录讲解完毕。流程讲的很明白,代码可能讲解的不是很多。最终的项目结构图:

这里写图片描述

哦,对了,别忘了在Uer_Master表中建一个测试账号:

这里写图片描述

最终运行的结果:

这里写图片描述

这里写图片描述

posted @ 2021-01-04 13:51  不要摸我的腰  阅读(204)  评论(0编辑  收藏  举报