這一篇介紹登錄的實現。
上一篇中我們已經將準備工作完成的差不多。我喜歡從後面往前面書寫代碼,這裏就按照我的思維順序進行編寫。
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>
@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表中建一個測試賬號:
最終運行的結果: