利用Cookies实现ASP.NET跨域单点登录

在一开始学习用ASP.NET来做登录的时候,都是用Session来做登录凭证的,但是由于后期网站的功能越来越多就想把网站的功能细分,而做成像CSDN一样各个网站子分类都有一个自己的域名如news.mysite.com, blog.mysite.com;但问题来了因为Session不能跨应用程序,然后在网站搜索,但找到的都是把子网站合并到主网站去,显示这种做法是极其不合理的;

然后以下是我的想法

不用Session做登录凭证而用Cookies来做登录凭证

1:然后在IIS中建立两个网站News.MySite.com,Blog.MySite.com (注这些在要Hosts文件中进行转向,不懂可以网上搜),注意一定要有域名的网站不然的话如网站主机头为127.0.0.1或者localhost这样的主机头没有办法保存域Cookies

2:在两个网站的Web.config中添加appsetting

<appSettings>

<add key="RootDomain" value="mysite.com"/>

<add key="PrivateKey" value="12345678"/>

</appSettings>

这是为了方便网站以后换域名的时候不用更改代码,PrivateKey是防止篡改Cookies而效仿网银功能添加多一个MD5验证功能

3:编写Cookies操作类

using System;
using System.Web;

namespace Z.Core.Tools
{
    /// <summary>
    /// Cookie 操作类
    /// </summary>
    public class Cookie
    {
        /// <summary>
        /// 设置一个Cookie
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="value">值</param>
        public static void Set(string name, string value)
        {
            Set(name, value, 0);
        }

        /// <summary>
        /// 设置一个Cookie
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="value">值</param>
        /// <param name="expiresDays">过期时间</param>
        public static void Set(string name, string value, int expiresDays)
        {
            //删除原先添加的相同Cookie
            foreach (string item in HttpContext.Current.Response.Cookies.AllKeys)
            {
                //判断为和当前已有的Cookie相同的时候进行remove
                if (item == name)
                {
                    HttpContext.Current.Response.Cookies.Remove(name);
                }
            }
            HttpCookie MyCookie = new HttpCookie(name);
            if (System.Configuration.ConfigurationManager.AppSettings["RootDomain"] == null)
            {
                throw new Exception(Lang.Define.Get(Lang.DefineEnum.RootDomain_未设置));
            }
            MyCookie.Domain = System.Configuration.ConfigurationManager.AppSettings["RootDomain"];
            if (value != null)
            {
                MyCookie.Value = System.Web.HttpUtility.UrlEncode(value).Replace("+", "%20");
            }
            //如果值为null的话说明删除这个cookie
            if (value == null && expiresDays == 0)
            {
                expiresDays = -1;
            }
            if (expiresDays != 0)
            {
                DateTime expires = DateTime.Now.AddDays(expiresDays);
                MyCookie.Expires = expires;
            }
            HttpContext.Current.Response.Cookies.Add(MyCookie);
        }

        /// <summary>
        /// 删除一个Cookie
        /// </summary>
        /// <param name="name">名称</param>
        public static void Delele(string name)
        {
            Set(name, "", -1);
        }

        /// <summary>
        /// 取得一个有效的Cookie
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>值</returns>
        public static string Get(string name)
        {
            string result = null;
            foreach (string item in HttpContext.Current.Response.Cookies.AllKeys)
            {
                if (item == name)
                {
                    if (HttpContext.Current.Response.Cookies[name].Expires > DateTime.Now || HttpContext.Current.Response.Cookies[name].Expires == new DateTime(1, 1, 1))
                    {
                        //如果判断到这个Cookie是有效的,取这个有效的新值
                        result = System.Web.HttpUtility.UrlDecode(HttpContext.Current.Response.Cookies[name].Value);
                        return result;
                    }
                    else
                    {
                        //无效的话还回null
                        return null;
                    }
                }
            }
            //如果在新添加中的没有就取客户端的
            if (HttpContext.Current.Request.Cookies[name] != null)
            {
                result = System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Cookies[name].Value.Replace("%20", "+"));
            }
            return result;
        }

        /// <summary>
        /// 清空Cookie
        /// </summary>
        public static void Clear()
        {
            for (int i = 0; i <= HttpContext.Current.Request.Cookies.Count - 1; i++)
            {
                //当Cookies的名称不为ASP.NET_SessionID的时候将他删除,因为删除了这个Cookies的话会导致重创建Session链接
                if (HttpContext.Current.Request.Cookies[i].Name.ToLower() != "asp.net_sessionid")
                {
                    Set(HttpContext.Current.Request.Cookies[i].Name, "", -1);
                }
            }
        }
    }
}

4:编写登录凭证类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Z.Core.Tools
{
    /// <summary>
    /// 网站Cookie集合
    /// </summary>
    public class CookieGroupTemplate
    {
        /// <summary>
        /// 登录User
        /// </summary>
        public static string UserCode
        {
            get
            {
                CheckKey();
                return Z.Core.Tools.Cookie.Get("UserCode");
            }
            set
            {
                Z.Core.Tools.Cookie.Set("UserCode", value);
                SetKey();
            }
        }

        /// <summary>
        /// 登录用户名
        /// </summary>
        public static string UserName
        {
            get
            {
                CheckKey();
                return Z.Core.Tools.Cookie.Get("UserName");
            }
            set
            {
                Z.Core.Tools.Cookie.Set("UserName", value);
                SetKey();
            }
        }

        /// <summary>
        /// 登录用户父级代码
        /// </summary>
        public static string ParentCode
        {
            get
            {
                CheckKey();
                return Z.Core.Tools.Cookie.Get("ParentCode"); ;
            }
            set
            {
                Z.Core.Tools.Cookie.Set("ParentCode", value);
                SetKey();
            }
        }

        /// <summary>
        /// 登录用户父级名称
        /// </summary>
        public static string ParentName
        {
            get
            {
                CheckKey();
                return Z.Core.Tools.Cookie.Get("ParentName");
            }
            set
            {
                Z.Core.Tools.Cookie.Set("ParentName", value);
                SetKey();
            }
        }

        /// <summary>
        /// 登录权限组
        /// </summary>
        public static string Groups
        {
            get
            {
                CheckKey();
                return Z.Core.Tools.Cookie.Get("Groups"); ;
            }
            set
            {
                Z.Core.Tools.Cookie.Set("Groups", value);
                SetKey();
            }
        }

        /// <summary>
        /// 操作位置
        /// </summary>
        public static string OperateFrom
        {
            get
            {
                return Z.Core.Tools.Cookie.Get("OperateFrom");
            }
            set
            {
                Z.Core.Tools.Cookie.Set("OperateFrom", value);
            }
        }

        /// <summary>
        /// 加密Cookies定义
        /// </summary>
        static List<string> CookieKeys = new List<string>()
        {
            "UserCode","UserName","ParentCode","ParentName","Groups","OperateFrom"
        };

        /// <summary>
        /// 生成验证Key
        /// </summary>
        static void SetKey()
        {
            string key = "";
            foreach (var s in CookieKeys)
            {
                key += s;
                key += "=";
                key += Cookie.Get(s);
                key += "&";
            }
            key += SettingGroupTemplate.PrivateKey;
            key = key.ToMD5();
            Cookie.Set("PrivateKey", key);
        }

        /// <summary>
        /// 验证Cookie
        /// </summary>
        static void CheckKey()
        {
            string key = "";
            foreach (var s in CookieKeys)
            {
                key += s;
                key += "=";
                key += Cookie.Get(s);
                key += "&";
            }
            string privateKey = Cookie.Get("PrivateKey");
            if (privateKey == null)
            {
                string _key = "";
                foreach (var s in CookieKeys)
                {
                    _key += s;
                    _key += "=";
                    _key += "&";
                }
                if (key == _key)
                {
                    SetKey();
                    return;
                }
            }
            key += SettingGroupTemplate.PrivateKey;
            key = key.ToMD5();
            if (privateKey == null)
            {

            }
            if (key != privateKey)
            {
                throw new ExceptionMessage(Lang.DefineEnum.Cookie验证出错.Define());
            }
        }
    }
}

----------------------------------------

好了,我默认在我的Cookies类中添加了几个常用到的值为读取这些Cookies的时候进行MD5验证,以保证Cookies的安全性

然后只要在你的网站项目中引用上面两个类,

然后在任意一个网站写入代码

Z.Core.Tools.CookieGroupTemplate.UserCode = "123";

然后在其他网站中用代码

Z.Core.Tools.CookieGroupTemplate.UserCode;

都可以读取得到这个登录用户的ID

是不是很简单啊。。。。

出处:http://www.cnblogs.com/JerryBaxia/archive/2010/08/22/1805648.html

  欢迎转载,但需保留版权。