【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表中建一個測試賬號:

這裏寫圖片描述

最終運行的結果:

這裏寫圖片描述

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章