利用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
欢迎转载,但需保留版权。
浙公网安备 33010602011771号