利用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
欢迎转载,但需保留版权。