zoukankan      html  css  js  c++  java
  • 基于Redis缓存的Session共享(附源码)

        在上一篇文章中我们研究了Redis的安装及一些基本的缓存操作,今天我们就利用Redis缓存实现一个Session共享,基于.NET平台的Seesion共享用的最多的应该是SQLServer数据库实现,我之前参与的一个项目么么亲子社区就是用的SQLSERVER实现不同子域名之间的Session共享。先打个广告嘿嘿,么么亲子网:enmuo.comi.enmuo.com就是通过SQLSERVER实现Session共享 欢迎大家访问。

    该片文章主要介绍主域名跟不同子域名之间的Session信息共享。

    纠正上一篇文章中关于RredisHelper类中的一个错误,就是要把设置缓存过期时间的代码放在设置完缓存值的后面,要不当第一次给该缓存键赋值的时候设置的缓存时间不管用,这个我也不知道为真么,具体修改如下:

    /// <summary>
    
            /// 添加单个实体到链表中
    
            /// </summary>
    
            /// <typeparam name="T"></typeparam>
    
            /// <param name="listId"></param>
    
            /// <param name="Item"></param>
    
            /// <param name="timeout"></param>
    
            public void AddEntityToList<T>(string listId, T Item, int timeout = 0)
    
            {
    
                IRedisTypedClient<T> iredisClient = Redis.As<T>();
    
              
    
                var redisList = iredisClient.Lists[listId];
    
                redisList.Add(Item);
    
                iredisClient.Save();
    
                if (timeout >= 0)
    
                {
    
                    if (timeout > 0)
    
                    {
    
                        secondsTimeOut = timeout;
    
                    }
    
                    Redis.Expire(listId, secondsTimeOut);
    
                }
    View Code

    下面我们开始进入正题,首先介绍一下CookieSession的关系

        我们都知道Session是存在Server端,Cookie是存在用户浏览器本地或内存中,用户在发起一个HTTP请求时,在请求的Header中会有Cookie信息,而Cookie中有一个ASP.NET_Sessionid的值,我们就是通过这个值获取到服务器端对应的Session信息。如下图所示:

     

    说明:图片中的token值是我的另一篇博文中用到的,本篇文章中不涉及该值。

    下面介绍一下我的思路

    1.  用户在给Session赋值的操作的时候我们可以为用户生成一个唯一的cookie值作为sessionID存储在用户的客户端,该cookie的key值可以自己命名,将该cookie值作为缓存的键和Session值一起存入到Redis缓存中。当然我们也可以直接用cookie中ASP.NET_Sessionid的值。
    2.  用户使用Session值得时候就可以根据cookie中的sessionId值在缓存中取出数据即可。

    程序实现逻辑:

    1、  我们新建一个如下项目,只用关注红线圈住的,其他没有用

     

    •  CookieHelper.cs Cookie操作,主要获取或生成SessionID值
    •  RredisHelper.cs 缓存操作,详见上一篇博文
    •  SessionHelper.cs 封装的Session操作

    2、  CookieHelper.cs文件

    在该文件中我们首先定义一个常量const string RedisSessionCookiesId = "RedisSessionCookiesId";作为cookie中存储SessionId的健。我们用Guid.NewGuid()

    生成一个唯一的值存储在cookie中作为SessionId的值,我们给cookie的Domain属性复制 "session.com",作为共享cookie的顶级域名。

    具体代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    
    namespace LONG.Common
    {
       public  class CookieHelper
        {
           //sessionId 的Key
            const string RedisSessionCookiesId = "RedisSessionCookiesId";
           /// <summary>
           /// 获取设置SessionID值
           /// </summary>
           /// <returns></returns>
            public static string CreatSessionCookie()
            {
                if (HttpContext.Current.Request.Cookies[RedisSessionCookiesId] != null)
                {
                    return HttpContext.Current.Request.Cookies[RedisSessionCookiesId].Value.ToString();
                }
                else
                {
                    Guid guid = Guid.NewGuid();
                    HttpCookie cokie = new HttpCookie(RedisSessionCookiesId);
                    cokie.Value = guid.ToString();
                    cokie.Expires = System.DateTime.Now.AddDays(1);
                    cokie.Domain = "session.com";
                    //cokie.Path = "/";
                    cokie.HttpOnly = true;
                    HttpContext.Current.Response.Cookies.Add(cokie);
                    return guid.ToString();
                }
            }
        }
    }
    View Code

    3、  RredisHelper.cs文件不做介绍,详见:http://www.cnblogs.com/lc-chenlong/archive/2013/07/26/3218157.html

    4、 SessionHelper.cs 文件

    通过索引器实现Session[“XX”]的取值赋值操作。对索引器不了解的童鞋可以百度一下。

    因为在一个项目中我们可以定义很多Session,比如Session[“name”]、Session[“url”]等,然而SessionID却只有一个值,那么我们怎么区分这些Session值呢,我们可以用SessionID+”_”+Session索引值实现,如:SessionID+”_name”、 SessionID+”_url”。

      代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    
    
    namespace LONG.Common
    {
        public class SessionHelper
        {
            
           public   RedisHelper Redis = new RedisHelper(true);
            public object this[string key]
            {
                get 
                {
                    key = CookieHelper.CreatSessionCookie() + "_" + key;
                    
                    //距离过期时间还有多少秒
                    long l = Redis.TTL(key);
                    return Redis.Get<object>(key); 
                }
                set 
                {
                    SetSession(key,value);
                }
            }
            public   void SetSession(string key,object value)
            {
                if (string.IsNullOrWhiteSpace(key))
                {
                    throw new Exception("Key is Null or Epmty");
                }
                key = CookieHelper.CreatSessionCookie() + "_"+key;
                Redis.Set<object>(key, value,60*3);
            }
            public string SessionId
            {
                get { return  CookieHelper.CreatSessionCookie();}
            }
        }
    }
    View Code

    对Session共享测试

    1、新建两个web项目

     

    2、我们在WebForm1.aspx.cs中添加如下代码:

     protected void Page_Load(object sender, EventArgs e)
            {
                test();
            }
            public void test()
            {
                SessionHelper Session = new SessionHelper();
                if (Session["user"] == null)
                {
                    Session["user"] = "eric";
                }
                //为了展示两个session的过期时间不一样,让线程休眠2s
                System.Threading.Thread.Sleep(2000);
                if(Session["url"]==null)
                {
                    Session["url"] = "http://baidu.com";
                }
                //Session["user"] = "qwewrwe";
                string text = string.Format("session['user']的值为:{0},距离过期时间:{1}秒", Session["user"].ToString(), Session.Redis.TTL(Session.SessionId + "_user"));
                text += "<br />";
                text += string.Format("session['url']的值为:{0},距离过期时间:{1}秒", Session["url"].ToString(), Session.Redis.TTL(Session.SessionId + "_url"));
                Response.Write(text);
    
            }
    View Code

    3、在Default.aspx中添加如下代码:

     public partial class _Default : System.Web.UI.Page
        {
            SessionHelper Session = new SessionHelper();
            
            protected void Page_Load(object sender, EventArgs e)
            {
                   Label1.Text= Session["user"].ToString()+"___"+Session["url"].ToString();
                
            }
            protected void Button1_Click(object sender, EventArgs e)
            {
                //改变Session["user"]的值
                Session["user"] = TextBox1.Text;
                Label1.Text = Session["user"].ToString()+"___"+Session["url"].ToString();
            }
        }
    View Code

    4、我在IIS想新建了两个项目:session.com(对应WebForm1.aspx项目)和b.session.com(对应Default.aspx项目)

     

     

    5、运行session.com下过如下:

     

    6、运行 b.session.com,我们发现我们获取到session.com站点的session值

     

    7、b.session.com在文本框中输入”陈龙”并点击【改变Session[user] 值】按钮。如下图:

     

    8、刷新session.com发现session[‘user’]的值已经改变,而且过期时间也被刷新。

     

    9、等到session.com 页面session[‘url’]的过期时间为0时刷新b.session.com

     

     

    说明Session值已过期。

    整个例子已经写完,如果文中有说的不对的地方欢迎指正。

    点击下载源码

    每天学习一点点,每天进步一点点。

  • 相关阅读:
    Lucene.Net 2.3.1开发介绍 —— 二、分词(一)
    控制‘控制台应用程序’的关闭操作
    详解for循环(各种用法)
    敏捷软件开发
    Sql Server的一些知识点
    在SharePoint 2010 中配置Remote Blob Storage FILESTREAM Provider
    使用LotusScript操作Lotus Notes RTF域
    JOpt Simple 4.5 发布,命令行解析器
    John the Ripper 1.8.0 发布,密码破解工具
    PacketFence ZEN 4.0.1 发布,网络接入控制
  • 原文地址:https://www.cnblogs.com/lc-chenlong/p/3221003.html
Copyright © 2011-2022 走看看