MVC使用Memcache+Cookie解决分布式系统共享登录状态学习笔记6

为了解决单机处理的瓶颈,增强软件的可用性,我们需要将软件部署在多台服务器上启用多个二级子域名以频道化的方式,根据业务功能将网站分布部署在独立的服务器上,或通过负载均衡技术(如:DNS轮询、Radware、F5、LVS等)让多个频道共享一组服务器。当我们将网站程序分部到多台服务器上后,由于Session受实现原理的局限,无法跨服务器同步更新Session,使得登录状态难以通过Session共享。

我们使用MemCache+Cookie方案来解决分布式系统共享登录状态的问题。

Memcache服务器本身就是一个Socket服务端,内部数据采用键值对的形式存储在服务器的内存中,本质就是一个大型的哈希表。数据的删除采用惰性删除机制。虽然Memcache并没有提供集群功能,但是通过客户端的驱动程序很容易就可以实现Memcache的集群配置。

先简单介绍一下Memcache的用法

1. 下载安装Memcache(Windows平台)

(1)将程序解压到磁盘任意位置

(2)进入cmd窗口,运行Memcached.exe -d install安装服务,安装后打开服务窗口查看服务是否安装成功。

(3)直接在服务管理中启动服务,或者使用cmd命令 net start "Memcache Server"

(4)使用Telnet连接到Memcache控制台,验证服务是否正常 telnet 127.0.0.1 11211

使用stats指令查看当前Memcache服务器状态

2. 程序中的用法

(1)在程序中添加 Memcached.ClientLibrary.dll的引用

(2)C#中操作Memcache的代码示例

String[] serverlist = { "192.168.1.100:11211",
"192.168.1.101:11211" };
// initialize the pool for memcache servers
SockIOPool pool = SockIOPool.GetInstance("test");
pool.SetServers(serverlist);
pool.Initialize();
mc = new MemcacheClient();
mc.PoolName = "test";
mc.EnableCompression = false;
pool.Shutdown();//关闭连接池

下面我们做方案的具体实现

1. 首先在Common层中引入Memcached.ClientLibrary.dll,并封装Memcache的帮助类,MemcacheHelper

using Memcached.ClientLibrary;
using System;

namespace PMS.Common
{
 public class MemcacheHelper
 {
 private static readonly MemcachedClient Mc = null;

 static MemcacheHelper()
 {
 //最好放在配置文件中
 string[] serverlist = { "127.0.0.1:11211", "10.0.0.132:11211" };

 //初始化池
 var pool = SockIOPool.GetInstance();
 pool.SetServers(serverlist);

 pool.InitConnections = 3;
 pool.MinConnections = 3;
 pool.MaxConnections = 5;

 pool.SocketConnectTimeout = 1000;
 pool.SocketTimeout = 3000;

 pool.MaintenanceSleep = 30;
 pool.Failover = true;

 pool.Nagle = false;
 pool.Initialize();

 // 获得客户端实例
 Mc = new MemcachedClient {EnableCompression = false};
 }
 /// <summary>
 /// 存储数据
 /// </summary>
 /// <param name="key"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public static bool Set(string key,object value)
 {
 return Mc.Set(key, value);
 }
 public static bool Set(string key, object value,DateTime time)
 {
 return Mc.Set(key, value,time);
 }
 /// <summary>
 /// 获取数据
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 public static object Get(string key)
 {
 return Mc.Get(key);
 }
 /// <summary>
 /// 删除
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 public static bool Delete(string key)
 {
 return Mc.KeyExists(key) && Mc.Delete(key);
 }
 }
}

2. 改变用户登录方法UserLogin,用户登录成功后生成GUID,将此GUID存入Cookie并以GUID为键将登录用户信息序列化存入Memcache服务器。

public ActionResult UserLogin()
{
 #region 验证码校验
 var validateCode = Session["validateCode"] != null ? Session["validateCode"].ToString() : string.Empty;
 if (string.IsNullOrEmpty(validateCode))
 return Content("no:验证码错误!!");
 Session["validateCode"] = null;
 var txtCode = Request["ValidateCode"];
 if (!validateCode.Equals(txtCode, StringComparison.InvariantCultureIgnoreCase))
 return Content("no:验证码错误!!");
 #endregion

 var userName = Request["UserName"];
 var userPwd = Request["PassWord"];
 //查询用户是否存在
 var user = UserService.LoadEntities(u => u.UserName == userName && u.PassWord == userPwd).FirstOrDefault();
 if (user == null) return Content("no:登录失败");

 //产生一个GUID值作为Memache的键.
 var sessionId = Guid.NewGuid().ToString();
 //将登录用户信息存储到Memcache中。
 MemcacheHelper.Set(sessionId, SerializeHelper.SerializeToString(user), DateTime.Now.AddMinutes(20));
 //将Memcache的key以Cookie的形式返回给浏览器。
 Response.Cookies["sessionId"].Value = sessionId;
 return Content("ok:登录成功");
}

3. 改变登录校验控制器FilterController的OnActionExecuting方法,使其校验方式改为从Memcache服务器中读取Cookie中值为键的对象:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
 base.OnActionExecuting(filterContext);
 //if (Session["user"] == null)
 if (Request.Cookies["sessionId"] != null)
 {
 var sessionId = Request.Cookies["sessionId"].Value;
 //根据该值查Memcache.
 var obj = MemcacheHelper.Get(sessionId);
 if (obj == null)
 {
 filterContext.Result = Redirect("/Login/Index");
 return;
 }
 var user = SerializeHelper.DeserializeToObject<User>(obj.ToString());
 LoginUser = user;
 //模拟出滑动过期时间.
 MemcacheHelper.Set(sessionId, obj, DateTime.Now.AddMinutes(20));
 }
 else
 filterContext.Result = Redirect("/Login/Index");
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Asp.Mvc 2.0实现用户登录与注销功能实例讲解(2)

    这一节讲解下ASP.MVC 2.0的用户登录与注销功能,先讲登录,后说注销.我们这个系列讲的用户登录方式都是FORM表单验证方式.在讲之前先给大家说下<%:%>的功能,<%:%>与<%=%>功能一样,用来动态输出内容. 一.登录 1. 建立MODEL 登录的时候,我们一般只要验证用户名和密码,还有是否保存登录COOKIE,所以我们建立一个MODEL登录类,只需包括3个字段就可以. /// <summary> /// 用户登录MODEL /// </su

  • ASP.NET MVC结合JavaScript登录、校验和加密

    最近闲来无事给自己写了家庭财务收支管理系统,也就包含支出管理,收入管理和一些统计功能. 先说登录模块,因为涉及GET和POST请求,这些东西都是能被监控和抓取的所以就考虑这使用RSA加密解密方式传输用户名和密码参数,页面JS如下: /*需要引入三个JS文件,BigInt.js.RSA.js和Barrett.js,用到cookie则需要引入jquery.cookie.js文件*/ //与后台交互获取公钥 function getPublicKey() { var pubKey = ''; if (

  • asp.net登录验证码实现方法

    前端添加的标签和方法: 验证码: 复制代码 代码如下: <input id="txtVerifyCode" type="text" maxlength="5" style="line-height: 30px;  height: 30px; width: 80px;border:solid 1px #d4d4d4;" class="input"/>&nbsp<img src=&qu

  • ASP.NET MVC5网站开发用户登录、注销(五)

    一.创建ClaimsIdentity ClaimsIdentity(委托基于声明的标识)是在ASP.NET Identity身份认证系统的登录时要用到,我们在UserService中来生成它. 1.打开IBLL项目InterfaceUserService接口,添加接口方法ClaimsIdentity CreateIdentity(User user, string authenticationType); 2.打开BLL项目的UserService类,添加CreateIdentity方法的实现代

  • ASP.NET Core集成微信登录

    工具: Visual Studio 2015 update 3 Asp.Net Core 1.0 1 准备工作 申请微信公众平台接口测试帐号,申请网址:(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login).申请接口测试号无需公众帐号,可以直接体验和测试公众平台所有高级接口. 1.1 配置接口信息 1.2 修改网页授权信息 点击"修改"后在弹出页面填入你的网站域名: 2 新建网站项目 2.1 选择ASP.NET C

  • MVC使用极验验证制作登录验证码学习笔记7

    在之前的项目中,如果有需要使用验证码,基本都是自己用GDI+画图出来,简单好用,但是却也存在了一些小问题,首先若较少干扰线,则安全性不是很高,验证码容易被机器识别,若多画太多干扰线条,机器人识别率下降的同时,人眼的识别率也同步下降(震惊哭).更为重要的是,GDI+绘制的验证码一般来说也不会很美观,如果做一个炫酷的登陆界面却配了这样一个验证码,画风诡异,丑到极致. 再后来浏览网页的过程中,发现很多很多网站项目中都使用了一种叫极验验证的验证码,采用移动滑块的方式进行验证,方便美观.而一番搜索之后了解

  • 基于C#后台调用跨域MVC服务及带Cookie验证的实现

    背景随着富客户端框架的盛行,以及众多优秀的前端js框架,很多情况我们会遇到跨域的问题,而js的ajax请求是不允许直接跨域访问的,当然你会说可以用JSONP等,但是由于代码洁癖,不想在前端和后台添加callback,而且很多情况你是无法控制的,需要牵连考虑太多的情况. 所以我直接绕过了,每个前端应用,自带一个通用后端服务代理,该服务解决跨域问题,自动代理帮前台获取跨域的数据. 如何算跨域虽然是个老问题,但是还是要提醒注意下两点:同IP,不同端口,数据访问是跨域的,但是Cookie访问是可以的(这

  • ASP.NET MVC5网站开发之登录、验证和注销管理员篇1(六)

    上次业务逻辑和展示层的架构都写了,可以开始进行具体功能的实现,这次先实现管理员的登录.验证和注销功能. 一.业务逻辑层1.实现256散列加密方法. Ninesky.Core[右键]-> 添加->文件夹,输入文件夹名General. General文件夹[右键]->添加->类,输入类名Security. 引用System.Security.Cryptography命名空间(1),并实现SHA256静态加密方法. 2.Administrator模型类 Ninesky.Core[右键]-

  • ASP.NET登录注册页面实现

    如何利用Visual  studio 2010创建一个ASP网站? [文件]-->[新建]-->[网站]-->[ASP.Net网站]--[完成] 默认页面Default.aspx 创建以上界面: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UserLogin.aspx.cs" Inherits="UserLogin" %> <

  • MVC使用Memcache+Cookie解决分布式系统共享登录状态学习笔记6

    为了解决单机处理的瓶颈,增强软件的可用性,我们需要将软件部署在多台服务器上启用多个二级子域名以频道化的方式,根据业务功能将网站分布部署在独立的服务器上,或通过负载均衡技术(如:DNS轮询.Radware.F5.LVS等)让多个频道共享一组服务器.当我们将网站程序分部到多台服务器上后,由于Session受实现原理的局限,无法跨服务器同步更新Session,使得登录状态难以通过Session共享. 我们使用MemCache+Cookie方案来解决分布式系统共享登录状态的问题. Memcache服务器

  • MVC项目结构搭建及单个类的实现学习笔记1

    新人刚开始学习ASP.NET MVC,若有不足之处希望能得到您的指点,不胜感激! 先来一张项目的层级结构图: Model:模型层,主要是各种类型.枚举以及ORM框架,框架完成数据库和实体类的映射.项目中选用了微软的开源ORM框架 EntityFramework 6.0 (以下简称EF),数据库则选择了微软的轻量级数据库SQL Server Compact 4.0本地数据库(简称Compact),Compact对EF支持比较完美,又属于文档型数据库,部署起来比较简洁. DAL:数据访问层,主要是对

  • php页面跳转session cookie丢失导致不能登录等问题的解决方法

    thinkphp开发的一个项目,登录成功后又跳转到登录页面,在提交信息后输出session都是正常的,没有问题,但是页面跳转后,session出现丢失现象,无法正常完成登陆. 通过查找资料,发现原来是bom头的原因.受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出(因为在COOKIE送出前PHP已经送出了文件头),所以登入和登出功能失效.一切依赖COOKIE.SESSION实现的功能全部无效. 正确的处理方法是去掉某些文件的bom,一般情况是在入口文件出现的

  • php使用cookie实现记住登录状态

    要实现记住密码自动登录的功能我们大多数据都是利用了客户端的cookies来实现,我们利用php也不例外,有需要的朋友可以参考一下. php制作记住密码自动登录的解决思路,其实也就是对session,cookies的操作 一.检查用户是否登录 复制代码 代码如下: //检查用户是否登录 function checklogin(){       if(empty($_SESSION['user_info'])){    //检查一下session是不是为空       if(empty($_COOK

  • jquery.cookie.js实现用户登录保存密码功能的方法

    本文实例讲述了jquery.cookie.js实现用户登录保存密码功能的方法.分享给大家供大家参考,具体如下: 需要导入的js有jquery.js和jquery.cookie.js <script type="text/javascript" src=" jquery-1.5.2.js"></script> <script type="text/javascript" src="jquery.cookie.

  • iOS中关于Cookie验证登录状态

    1.第一次进入应用,登录获取Cookie,此时如果用到的是AFN去获取接口数据,Cookie已经写入了,所以无需处理,每次请求的时候,会自动将该cookie传给后台去验证 2.将Cookie缓存到本地: NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]]; NSUserDefaults *default

  • python通过cookie模拟已登录状态的初步研究

    对于那些需要在登录环境下进行的爬虫操作,模拟登陆或伪装已登录状态是一个刚需. 分析了网上关于模拟登录的例子,很多都基于用户名/密码发起一个post请求,遇到有图片验证码的,比较理想的方法是进行人工干预,同步发起一个图片验证码的请求,将图片写到本地,人工查看后进行输入. 既然,少不了人工干预,为何登录操作不全程人工进行,已登录后再把浏览器的Cookie信息全拷贝出来,通过爬虫伪造成一个已登录的浏览器呢? 我暂时试了试国内的几个大网站,发现都行得通,可以模拟浏览器进行登录之后的很多操作,包括签到,修

  • PHP根据session与cookie用户登录状态操作类的代码

     1.用户登录状态操作类UserLogin <?php final class UserLogin { public function __construct() { } public static function getUserInfo() { if (isset($_COOKIE["user_id"])&&$_COOKIE["user_id"]&&(trim($_COOKIE["user_id"])!=

  • php中如何同时使用session和cookie来保存用户登录信息

    同时使用session和cookie来保存用户登录信息1.数据库连接配置页面:connectvars.php 复制代码 代码如下: <?php//数据库的位置define('DB_HOST', '127.0.0.1');//用户名define('DB_USER', 'root');//口令define('DB_PASSWORD', '19900101');//数据库名define('DB_NAME','test') ;?> 2.登录页面:logIn.php 复制代码 代码如下: <?ph

随机推荐