一、多站点共享用户信息解决方案:
采用分布式缓存Memcache模拟Session进行用户信息信息共享
1、视图部分
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>XX商城后台管理系统登录</title> <script type="text/javascript"> if (window.parent.window != window) { window.top.location.href = "/Home/CheckLogin"; } </script> <script src="~/Scripts/jquery-1.8.2.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> <script type="text/javascript"> function changeCheckCode() { $("#img").attr("src", $("#img").attr("src") + 1); } function afterLogin(data) { if (data=="ok") { window.location.href = "/Home/Index"; } else { $("#errorMsg").text(data); changeCheckCode(); } } </script> <style type="text/css"> * { padding: 0; margin: 0; } body { text-align: center; background: #4974A4; } #login { width: 740px; margin: 0 auto; font-size: 12px; } #loginlogo { width: 700px; height: 100px; overflow: hidden; background: url('/Content/Images/login/logo.png') no-repeat; margin-top: 50px; } #loginpanel { width: 729px; position: relative; height: 300px; } .panel-h { width: 729px; height: 20px; background: url('/Content/Images/login/panel-h.gif') no-repeat; position: absolute; top: 0px; left: 0px; z-index: 3; } .panel-f { width: 729px; height: 13px; background: url('/Content/Images/login/panel-f.gif') no-repeat; position: absolute; bottom: 0px; left: 0px; z-index: 3; } .panel-c { z-index: 2; background: url('/Content/Images/login/panel-c.gif') repeat-y; width: 729px; height: 300px; } .panel-c-l { position: absolute; left: 60px; top: 40px; } .panel-c-r { position: absolute; right: 20px; top: 50px; width: 222px; line-height: 200%; text-align: left; } .panel-c-l h3 { color: #556A85; margin-bottom: 10px; } .panel-c-l td { padding: 7px; } .login-text { height: 24px; left: 24px; border: 1px solid #e9e9e9; background: #f9f9f9; } .login-text-focus { border: 1px solid #E6BF73; } .login-btn { width: 114px; height: 29px; color: #E9FFFF; line-height: 29px; background: url('/Content/Images/login/login-btn.gif') no-repeat; border: none; overflow: hidden; cursor: pointer; } #txtUsername, #code, #txtPassword { width: 191px; } #logincopyright { text-align: center; color: White; margin-top: 50px; } a { color: Black; } a:hover { color: Red; text-decoration: underline; } </style> </head> <body style="padding: 10px"> <div id="login"> <div id="loginlogo"> </div> <div id="loginpanel"> <div class="panel-h"> </div> <div class="panel-c"> <div class="panel-c-l"> @using (Ajax.BeginForm("CheckLogin", new { }, new AjaxOptions() { OnSuccess = "afterLogin" }, new { id = "loginForm" })) { <table cellpadding="0" cellspacing="0"> <tbody> <tr> <td align="left" colspan="2"> <h3> 请使用OA系统账号登录 </h3> </td> </tr> <tr> <td align="right"> 账号: </td> <td align="left"> <input type="text" name="LoginCode" id="LoginCode" class="login-text" /> </td> </tr> <tr> <td align="right"> 密码: </td> <td align="left"> <input type="password" name="LoginPwd" id="LoginPwd" value="123" class="login-text" /> </td> </tr> <tr> <td> 验证码: </td> <td align="left"> <input type="text" class="login-text" id="code" name="vCode" value="1" /> </td> </tr> <tr> <td></td> <td> <img id="img" src="/Login/ValidateCode/?id=1" style="float: left; height: 24px;" /> <div style="float: left; margin-left: 5px; margin-top: 10px;"> <a href="javascript:void(0)" onclick="changeCheckCode();return false;">看不清,换一张</a> </div> </td> </tr> <tr> <td align="center" colspan="2"> <input type="submit" id="btnLogin" value="登录" class="login-btn" /><a href="/Login/FindPwd">找回密码</a> <input type="checkbox" name="checkMe" value="1" />记住我 <span id="errorMsg"></span> </td> </tr> </tbody> </table> } </div> <div class="panel-c-r"> <p> 请从左侧输入登录账号和密码登录 </p> <p> 如果遇到系统问题,请联系网络管理员。 </p> <p> 如果没有账号,请联系网站管理员。 </p> <p> ...... </p> </div> </div> <div class="panel-f"> </div> </div> <div id="logincopyright"> Copyright ? 2012 Yilian.com </div> </div> </body> </html>
登录页面展示:
2、控制器部分
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace WebApp.Controllers { public class LoginController : Controller { // GET: /Login/ CZBK.HeiMaOA.IBLL.IUserInfoService userInfoService { get; set; } public ActionResult Index() { return View(); } #region 用户登录 public ActionResult CheckLogin() { string validateCode = Session["validateCode"] == null ? string.Empty : Session["validateCode"].ToString(); if (string.IsNullOrEmpty(validateCode)) { return Content("验证码错误!"); } //清空防止暴力破解 Session["validateCode"] = null; string requestCode = Request["vCode"]; if (!requestCode.Equals(validateCode, StringComparison.InvariantCultureIgnoreCase)) { return Content("验证码错误!"); } string userName = Request["LoginCode"]; string userPwd = Request["LoginPwd"]; //对用户名、密码进行过滤 var userInfo = userInfoService.LoadEntities(u => u.UName == userName && u.UPwd == userPwd).FirstOrDefault(); if (userInfo == null) { return Content("用户名密码错误!"); } else { //Session["userInfo"] = userInfo; //普通方式 #region 利用Memcache模拟Session进行共享用户Session信息 //自己创建的SessionId,作为Memcache的Key string sessionId = Guid.NewGuid().ToString(); //将用户的信息存储到Memcache中 CZBK.HeiMaOA.Common.MemcacheHelper.Set(sessionId, CZBK.HeiMaOA.Common.SerializerHelper.SerializerToString(userInfo)); //然后将自创的SessionId以Cookie的形式返回给浏览器,存储到浏览器端的内存中。 Response.Cookies["sessionId"].Value = sessionId; #endregion return Content("ok"); } } #endregion #region 展示验证码 public ActionResult ValidateCode() { CZBK.HeiMaOA.Common.ValidateCode validateCode = new CZBK.HeiMaOA.Common.ValidateCode(); string code = validateCode.CreateValidateCode(4); Session["validateCode"] = code; byte[] buffer = validateCode.CreateValidateGraphic(code); return File(buffer, "image/jpeg"); } #endregion } }
二、访问页面先验证用户是否登录的解决办法:
1.新建BaseController,让需要验证的继承这个控制器即可:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using CZBK.HeiMaOA.Model; namespace WebApp.Controllers { public class BaseController : Controller { public UserInfo LoginUser { get; set; } /// <summary> /// 执行控制器方法之前先执行该方法 /// 获取自定义SessionId的值,然后从Memcache中取出 /// </summary> /// <param name="filterContext"></param> protected override void OnActionExecuting(ActionExecutingContext filterContext) { bool isExt = false; if (Request.Cookies["sessionId"] != null) { //获取自定义的SessionId string sessionId = Request.Cookies["sessionId"].Value; object obj = CZBK.HeiMaOA.Common.MemcacheHelper.Get(sessionId); if (obj != null) { LoginUser = CZBK.HeiMaOA.Common.SerializerHelper.DeserializeToObject<UserInfo>(obj.ToString()); isExt = true; } } if (!isExt) //用户没登录 { filterContext.HttpContext.Response.Redirect("/Login/Index"); } base.OnActionExecuting(filterContext); } } }
2.示例:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace WebApp.Controllers { public class HomeController : BaseController { // // GET: /Home/ public ActionResult Index() { if (LoginUser != null) { ViewData["userName"] = LoginUser.UName; } return View(); } } }
三、源码下载:
点击下载源码>>
点击下载数据库文件>>