asp.net 跨域单点登录
asp.net 跨域单点登录
关键字:单点登录 跨域 跨域单点登录
源代码下载:http://download.csdn.net/source/1571879
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
asp.net跨域单点登录分为:
1、跨子域单点登录。如 blog.a.com 和 info.a.com 这2个站点同属一个主域.a.com,实现跨子域单点登录很简单,可以利用cookie,设置Domain为".a.com'即可,这里就不再赘叙。
2、完成跨域单点登录。如 www.a.com www.b.com 这2个站点之间实现共享一个身份验证系统,只需在一处地方登录,下面主要谈下这种方式的实现方法。
asp.net 跨域单点登录实现原理:
当用户第一次访问web应用系统1的时候,因为还没有登录,会被引导到认证中心进行登录;根据用户提供的登录信息,认证系统进行身份效验,如果通过效验,返回给用户一个认证的凭据;用户再访问别的web应用的时候就会将这个Token带上,作为自己认证的凭据,应用系统接受到请求之后会把Token送到认证中心进行效验,检查Token的合法性。如果通过效验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。所有应用系统共享一个身份认证系统。认证系统的主要功能是将用户的登录信息和用户信息库相比较,对用户进行登录认证;认证成功后,认证系统应该生成统一的认证标志,返还给用户。另外,认证系统还应该对Token进行效验,判断其有效性。 所有应用系统能够识别和提取Token信息要实现SSO的功能,让用户只登录一次,就必须让应用系统能够识别已经登录过的用户。应用系统应该能对Token进行识别和提取,通过与认证系统的通讯,能自动判断当前用户是否登录过,从而完成单点登录的功能。
比如说,我现在有3个分站点和1个认证中心(总站)。当用户访问分站点的时候,分站点会发Token到验证中心进行验证。验证中心判断用户是否已经登录。如果未登录,则返回到验证中心登录入口进行登录,否之则返回Token验证到分站点,直接进入分站点。
如图所示:
上面是实现单点登录的原理图,下面介绍下如何用asp.net实现跨域单点登录:
一、新建网站 MasterSite,作为总站认证中心。配置web.config,采用form登录验证。
配置如下:
- <authentication mode="Forms">
- <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="120">
- </forms>
- </authentication>
- <authorization>
- <!--拒绝所有匿名用户-->
- <deny users="?"/>
- </authorization>
添加Default.aspx页面,用来进行登录。代码如下:
HTML Code:
- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" >
- <head runat="server">
- <title>总站登录</title>
- </head>
- <body>
- <form id="form1" runat="server">
- <div>
- <asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate" UserName="test">
- </asp:Login>
- </div>
- </form>
- </body>
- </html>
Default.cs Code:
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- using System.Text;
- public partial class _Default : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!IsPostBack)
- {
- SSORequest ssoRequest = new SSORequest();
- #region 验证 Post 过来的参数
- //--------------------------------
- // 请求注销
- if (!string.IsNullOrEmpty(Request["Logout"]))
- {
- Authentication.Logout();
- return;
- }
- //--------------------------------
- // 各独立站点标识
- if (string.IsNullOrEmpty(Request["IASID"]))
- {
- return;
- }
- else
- {
- ssoRequest.IASID = Request["IASID"];
- }
- //--------------------------------
- // 时间戳
- if (string.IsNullOrEmpty(Request["TimeStamp"]))
- {
- return;
- }
- else
- {
- ssoRequest.TimeStamp = Request["TimeStamp"];
- }
- //--------------------------------
- // 各独立站点的访问地址
- if (string.IsNullOrEmpty(Request["AppUrl"]))
- {
- return;
- }
- else
- {
- ssoRequest.AppUrl = Request["AppUrl"];
- }
- //--------------------------------
- // 各独立站点的 Token
- if (string.IsNullOrEmpty(Request["Authenticator"]))
- {
- return;
- }
- else
- {
- ssoRequest.Authenticator = Request["Authenticator"];
- }
- ViewState["SSORequest"] = ssoRequest;
- #endregion
- //验证从分站发过来的Token
- if (Authentication.ValidateAppToken(ssoRequest))
- {
- string userAccount = null;
- // 验证用户之前是否登录过
- //验证 EAC 认证中心的 Cookie,验证通过时获取用户登录账号
- if (Authentication.ValidateEACCookie(out userAccount))
- {
- ssoRequest.UserAccount = userAccount;
- //创建认证中心发往各分站的 Token
- if (Authentication.CreateEACToken(ssoRequest))
- {
- Post(ssoRequest);
- }
- }
- else
- {
- return;
- }
- }
- else
- {
- return;
- }
- }
- }
- //post请求
- void Post(SSORequest ssoRequest)
- {
- PostService ps = new PostService();
- ps.Url = ssoRequest.AppUrl;
- ps.Add("UserAccount", ssoRequest.UserAccount);
- ps.Add("IASID", ssoRequest.IASID);
- ps.Add("TimeStamp", ssoRequest.TimeStamp);
- ps.Add("AppUrl", ssoRequest.AppUrl);
- ps.Add("Authenticator", ssoRequest.Authenticator);
- ps.Post();
- }
- /// <summary>
- /// 验证登录账号和密码是否正确
- /// </summary>
- /// <param name="userName">登录账号</param>
- /// <param name="userPwd">登录密码</param>
- /// <returns></returns>
- private bool ValidateUserInfo(string userName, string userPwd)
- {
- //从数据库中读取,验证登录账号和密码
- //略...
- return true;
- }
- protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
- {
- if (string.IsNullOrEmpty(Login1.UserName) || string.IsNullOrEmpty(Login1.Password))
- {
- Page.RegisterClientScriptBlock("Add", "<mce:script lanuage=/"javascript/"><!--
- alert('用户名密码不能为空!');
- // --></mce:script>");
- return;
- }
- else if (ValidateUserInfo(Login1.UserName, Login1.Password) == false)
- {
- Page.RegisterClientScriptBlock("Add", "<mce:script lanuage=/"javascript/"><!--
- alert('用户名密码错误!');
- // --></mce:script>");
- return;
- }
- else
- {
- Session["CurrUserName"] = Login1.UserName;
- Session.Timeout = 120;
- SSORequest ssoRequest = ViewState["SSORequest"] as SSORequest;
- // 如果不是从各分站 Post 过来的请求,则默认登录主站
- if (ssoRequest == null)
- {
- FormsAuthentication.SetAuthCookie(Login1.UserName, false);
- ssoRequest = new SSORequest();
- //主站标识ID
- ssoRequest.IASID = "00";
- ssoRequest.AppUrl = "SiteList.aspx";
- ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
- ssoRequest.Authenticator = string.Empty;
- Response.Redirect("SiteList.aspx");
- }
- ssoRequest.UserAccount = Login1.UserName;
- //创建Token
- if (Authentication.CreateEACToken(ssoRequest))
- {
- string expireTime = DateTime.Now.AddHours(3).ToString("yyyy-MM-dd HH:mm");
- Authentication.CreatEACCookie(ssoRequest.UserAccount, ssoRequest.TimeStamp, expireTime);
- Post(ssoRequest);
- }
- }
- }
- }
代码说明:验证分站post过来的Token请求,如果用户已经登录,则创建认证中心发往各分站的 Token验证,转向分站,否之则返回登录。若是直接登录主站则转向站点选择页面sitelist.aspx,选择你要登录的分站点。
如图:
二、新建站点1,代码如下:
HTML Code:
- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" >
- <head runat="server">
- <title> 站点一</title>
- </head>
- <body>
- <form id="form1" runat="server">
- <div>
- <br />
- <br />
- <asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">返回主站</asp:LinkButton>
- <asp:LinkButton ID="LinkButton2" runat="server" OnClick="LinkButton2_Click">注销登录</asp:LinkButton></div>
- </form>
- </body>
- </html>
Default.cs code:
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- using System.Text;
- public partial class _Default : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!IsPostBack)
- {
- #region SSO 部分代码
- SSORequest ssoRequest = new SSORequest();
- if (string.IsNullOrEmpty(Request["IASID"]))
- {
- ssoRequest.IASID = "01";
- ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
- ssoRequest.AppUrl = Request.Url.ToString();
- Authentication.CreateAppToken(ssoRequest);
- Post(ssoRequest);
- }
- else if (!string.IsNullOrEmpty(Request["IASID"])
- && !string.IsNullOrEmpty(Request["TimeStamp"])
- && !string.IsNullOrEmpty(Request["AppUrl"])
- && !string.IsNullOrEmpty(Request["UserAccount"])
- && !string.IsNullOrEmpty(Request["Authenticator"]))
- {
- ssoRequest.IASID = Request["IASID"];
- ssoRequest.TimeStamp = Request["TimeStamp"];
- ssoRequest.AppUrl = Request["AppUrl"];
- ssoRequest.UserAccount = Request["UserAccount"];
- ssoRequest.Authenticator = Request["Authenticator"];
- if (Authentication.ValidateEACToken(ssoRequest))
- {
- //从数据库中获取UserId
- Session["CurrUserName"] = Request["UserAccount"];
- Session.Timeout = 120;
- FormsAuthentication.SetAuthCookie(Request["UserAccount"], false);
- Response.Write(string.Format("{0},您好!欢迎来到site1, >> 访问<a href="/" mce_href="/""http://localhost/Site2/Default.aspx/">site2</a>",ssoRequest.UserAccount));
- }
- }
- ViewState["SSORequest"] = ssoRequest;
- #endregion
- }
- }
- void Post(SSORequest ssoRequest)
- {
- PostService ps = new PostService();
- //认证中心(主站)地址
- string EACUrl = "http://localhost/MasterSite/Default.aspx";
- ps.Url = EACUrl;
- //ps.Add("UserAccount", ssoRequest.UserAccount);
- ps.Add("IASID", ssoRequest.IASID);
- ps.Add("TimeStamp", ssoRequest.TimeStamp);
- ps.Add("AppUrl", ssoRequest.AppUrl);
- ps.Add("Authenticator", ssoRequest.Authenticator);
- ps.Post();
- }
- //注销登录
- protected void LinkButton2_Click(object sender, EventArgs e)
- {
- FormsAuthentication.SignOut();
- SSORequest ssoRequest = new SSORequest();
- ssoRequest.IASID = "01";
- ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
- ssoRequest.AppUrl = Request.Url.ToString();
- Authentication.CreateAppToken(ssoRequest);
- PostService ps = new PostService();
- //认证中心(主站)地址
- string EACUrl = "http://localhost/MasterSite/Default.aspx";
- ps.Url = EACUrl;
- ps.Add("IASID", ssoRequest.IASID);
- ps.Add("TimeStamp", ssoRequest.TimeStamp);
- ps.Add("AppUrl", ssoRequest.AppUrl);
- ps.Add("Authenticator", ssoRequest.Authenticator);
- ps.Add("Logout", "true");
- ps.Post();
- }
- //返回主站
- protected void LinkButton1_Click(object sender, EventArgs e)
- {
- if (Session["CurrUserName"] != null)
- {
- Response.Redirect("http://localhost/MasterSite/SiteList.aspx");
- }
- }
- }
配置web.config
- <authentication mode="Forms">
- <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="60">
- </forms>
- </authentication>
- <authorization>
- <!--拒绝所有匿名用户-->
- <deny users="?"/>
- </authorization>
三、同二一样,新建站点Site2,代码如下:
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- public partial class _Default : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!IsPostBack)
- {
- #region SSO 部分代码
- SSORequest ssoRequest = new SSORequest();
- if (string.IsNullOrEmpty(Request["IASID"]))
- {
- ssoRequest.IASID = "02";
- ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
- ssoRequest.AppUrl = Request.Url.ToString();
- Authentication.CreateAppToken(ssoRequest);
- Post(ssoRequest);
- }
- else if (!string.IsNullOrEmpty(Request["IASID"])
- && !string.IsNullOrEmpty(Request["TimeStamp"])
- && !string.IsNullOrEmpty(Request["AppUrl"])
- && !string.IsNullOrEmpty(Request["UserAccount"])
- && !string.IsNullOrEmpty(Request["Authenticator"]))
- {
- ssoRequest.IASID = Request["IASID"];
- ssoRequest.TimeStamp = Request["TimeStamp"];
- ssoRequest.AppUrl = Request["AppUrl"];
- ssoRequest.UserAccount = Request["UserAccount"];
- ssoRequest.Authenticator = Request["Authenticator"];
- if (Authentication.ValidateEACToken(ssoRequest))
- {
- Session["CurrUserName"] = Request["UserAccount"];
- Session.Timeout = 120;
- FormsAuthentication.SetAuthCookie(Request["UserAccount"], false);
- Response.Write(string.Format("{0},您好!欢迎来到site2, >> 访问<a href="/" mce_href="/""http://localhost/Site1/Default.aspx/">site1</a>", ssoRequest.UserAccount));
- }
- }
- ViewState["SSORequest"] = ssoRequest;
- #endregion
- }
- }
- void Post(SSORequest ssoRequest)
- {
- PostService ps = new PostService();
- //认证中心(主站)地址
- string EACUrl = "http://localhost/MasterSite/Default.aspx";
- ps.Url = EACUrl;
- //ps.Add("UserAccount", ssoRequest.UserAccount);
- ps.Add("IASID", ssoRequest.IASID);
- ps.Add("TimeStamp", ssoRequest.TimeStamp);
- ps.Add("AppUrl", ssoRequest.AppUrl);
- ps.Add("Authenticator", ssoRequest.Authenticator);
- ps.Post();
- }
- //注销登录
- protected void LinkButton2_Click(object sender, EventArgs e)
- {
- FormsAuthentication.SignOut();
- SSORequest ssoRequest = new SSORequest();
- ssoRequest.IASID = "02";
- ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
- ssoRequest.AppUrl = Request.Url.ToString();
- Authentication.CreateAppToken(ssoRequest);
- PostService ps = new PostService();
- //认证中心(主站)地址
- string EACUrl = "http://localhost/MasterSite/Default.aspx";
- ps.Url = EACUrl;
- ps.Add("IASID", ssoRequest.IASID);
- ps.Add("TimeStamp", ssoRequest.TimeStamp);
- ps.Add("AppUrl", ssoRequest.AppUrl);
- ps.Add("Authenticator", ssoRequest.Authenticator);
- ps.Add("Logout", "true");
- ps.Post();
- }
- //返回主站
- protected void LinkButton1_Click(object sender, EventArgs e)
- {
- if (Session["CurrUserName"] != null)
- {
- Response.Redirect("http://localhost/MasterSite/SiteList.aspx");
- }
- }
- }
对于tokent请求,tokent验证,需要对它进行加密、解密。
其它代码:
Authentication.cs
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Collections.Generic;
- using System.Text;
- /// <summary>
- /// 安全验证类
- /// </summary>
- public class Authentication
- {
- static readonly string cookieName = "EACToken";
- static readonly string hashSplitter = "|";
- public Authentication()
- {
- }
- public static string GetAppKey(int appID)
- {
- //string cmdText = @"select * from ";
- return string.Empty;
- }
- public static string GetAppKey()
- {
- return "22362E7A9285DD53A0BBC2932F9733C505DC04EDBFE00D70";
- }
- public static string GetAppIV()
- {
- return "1E7FA9231E7FA923";
- }
- /// <summary>
- /// 取得加密服务
- /// </summary>
- /// <returns></returns>
- static CryptoService GetCryptoService()
- {
- string key = GetAppKey();
- string IV = GetAppIV();
- CryptoService cs = new CryptoService(key, IV);
- return cs;
- }
- /// <summary>
- /// 创建各分站发往认证中心的 Token
- /// </summary>
- /// <param name="ssoRequest"></param>
- /// <returns></returns>
- public static bool CreateAppToken(SSORequest ssoRequest)
- {
- string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
- string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
- string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
- byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
- CryptoService cs = GetCryptoService();
- byte[] encrypted;
- if (cs.Encrypt(bToEncrypt, out encrypted))
- {
- ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
- return true;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 验证从各分站发送过来的 Token
- /// </summary>
- /// <param name="ssoRequest"></param>
- /// <returns></returns>
- public static bool ValidateAppToken(SSORequest ssoRequest)
- {
- string Authenticator = ssoRequest.Authenticator;
- string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
- string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
- string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
- byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
- CryptoService cs = GetCryptoService();
- byte[] encrypted;
- if (cs.Encrypt(bToEncrypt, out encrypted))
- {
- return Authenticator == CryptoHelper.ToBase64String(encrypted);
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 创建认证中心发往各分站的 Token
- /// </summary>
- /// <param name="ssoRequest"></param>
- /// <returns></returns>
- public static bool CreateEACToken(SSORequest ssoRequest)
- {
- string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
- string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
- string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
- byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
- CryptoService cs = GetCryptoService();
- byte[] encrypted;
- if (cs.Encrypt(bToEncrypt, out encrypted))
- {
- ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
- return true;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 验证从认证中心发送过来的 Token
- /// </summary>
- /// <param name="ssoRequest"></param>
- /// <returns></returns>
- public static bool ValidateEACToken(SSORequest ssoRequest)
- {
- string Authenticator = ssoRequest.Authenticator;
- string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
- string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
- string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
- byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
- string EncryCurrentAuthenticator = string.Empty;
- CryptoService cs = GetCryptoService();
- byte[] encrypted;
- if (cs.Encrypt(bToEncrypt, out encrypted))
- {
- EncryCurrentAuthenticator = CryptoHelper.ToBase64String(encrypted);
- return Authenticator == EncryCurrentAuthenticator;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 创建 EAC 认证中心的 Cookie
- /// </summary>
- /// <param name="userAccount"></param>
- /// <param name="timeStamp"></param>
- /// <param name="expireTime"></param>
- /// <param name="cookieValue"></param>
- /// <returns></returns>
- public static bool CreatEACCookie(string userAccount, string timeStamp, string expireTime)
- {
- string plainText = "UserAccount=" + userAccount + ";TimeStamp=" + timeStamp + ";ExpireTime=" + expireTime;
- plainText += hashSplitter + CryptoHelper.ComputeHashString(plainText);
- CryptoService cs = GetCryptoService();
- byte[] encrypted;
- if (cs.Encrypt(CryptoHelper.ConvertStringToByteArray(plainText), out encrypted))
- {
- string cookieValue = CryptoHelper.ToBase64String(encrypted);
- SetCookie(cookieValue);
- return true;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 验证 EAC 认证中心的 Cookie,验证通过时获取用户登录账号
- /// </summary>
- /// <param name="userAccount">输出用户登录账号</param>
- /// <returns></returns>
- public static bool ValidateEACCookie(out string userAccount)
- {
- userAccount = string.Empty;
- try
- {
- string cookieValue = GetCookie().Value;
- byte[] toDecrypt = CryptoHelper.FromBase64String(cookieValue);
- CryptoService cs = GetCryptoService();
- string decrypted = string.Empty;
- if (cs.Decrypt(toDecrypt, out decrypted))
- {
- string[] arrTemp = decrypted.Split(Convert.ToChar(hashSplitter));
- string plainText = arrTemp[0];
- string hashedText = arrTemp[1];
- userAccount = plainText.Split(Convert.ToChar(";"))[0].Split(Convert.ToChar("="))[1];
- return hashedText.Replace("/0", string.Empty) == CryptoHelper.ComputeHashString(plainText);
- }
- else
- {
- return false;
- }
- }
- catch (Exception e)
- {
- return false;
- }
- }
- public static void Logout()
- {
- HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Parse("1900-1-1");
- HttpContext.Current.Response.Cookies[cookieName].Path = "/";
- }
- private static void SetCookie(string cookieValue)
- {
- HttpContext.Current.Response.Cookies[cookieName].Value = cookieValue;
- HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Now.AddHours(24);
- HttpContext.Current.Response.Cookies[cookieName].Path = "/";
- }
- private static HttpCookie GetCookie()
- {
- HttpCookie cookie = HttpContext.Current.Request.Cookies["EACToken"];
- return cookie;
- }
- }
CryptoHelper.cs
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Security.Cryptography;
- public class CryptoHelper
- {
- /// <summary>
- /// 复合 Hash:string --> byte[] --> hashed byte[] --> base64 string
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public static string ComputeHashString(string s)
- {
- return ToBase64String(ComputeHash(ConvertStringToByteArray(s)));
- }
- public static byte[] ComputeHash(byte[] buf)
- {
- //return ((HashAlgorithm)CryptoConfig.CreateFromName("SHA1")).ComputeHash(buf);
- return SHA1.Create().ComputeHash(buf);
- }
- /// <summary>
- /// //System.Convert.ToBase64String
- /// </summary>
- /// <param name="buf"></param>
- /// <returns></returns>
- public static string ToBase64String(byte[] buf)
- {
- return System.Convert.ToBase64String(buf);
- }
- public static byte[] FromBase64String(string s)
- {
- return System.Convert.FromBase64String(s);
- }
- /// <summary>
- /// //Encoding.UTF8.GetBytes(s)
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public static byte[] ConvertStringToByteArray(String s)
- {
- return Encoding.UTF8.GetBytes(s);//gb2312
- }
- public static string ConvertByteArrayToString(byte[] buf)
- {
- //return System.Text.Encoding.GetEncoding("utf-8").GetString(buf);
- return Encoding.UTF8.GetString(buf);
- }
- /// <summary>
- /// 字节数组转换为十六进制字符串
- /// </summary>
- /// <param name="buf"></param>
- /// <returns></returns>
- public static string ByteArrayToHexString(byte[] buf)
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < buf.Length; i++)
- {
- sb.Append(buf[i].ToString("X").Length == 2 ? buf[i].ToString("X") : "0" + buf[i].ToString("X"));
- }
- return sb.ToString();
- }
- /// <summary>
- /// 十六进制字符串转换为字节数组
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public static byte[] HexStringToByteArray(string s)
- {
- Byte[] buf = new byte[s.Length / 2];
- for (int i = 0; i < buf.Length; i++)
- {
- buf[i] = (byte)(Char2Hex(s.Substring(i * 2, 1)) * 0x10 + Char2Hex(s.Substring(i * 2 + 1, 1)));
- }
- return buf;
- }
- private static byte Char2Hex(string chr)
- {
- switch (chr)
- {
- case "0":
- return 0x00;
- case "1":
- return 0x01;
- case "2":
- return 0x02;
- case "3":
- return 0x03;
- case "4":
- return 0x04;
- case "5":
- return 0x05;
- case "6":
- return 0x06;
- case "7":
- return 0x07;
- case "8":
- return 0x08;
- case "9":
- return 0x09;
- case "A":
- return 0x0a;
- case "B":
- return 0x0b;
- case "C":
- return 0x0c;
- case "D":
- return 0x0d;
- case "E":
- return 0x0e;
- case "F":
- return 0x0f;
- }
- return 0x00;
- }
- }
CryptoService.cs
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- using System.Text;
- using System.Security.Cryptography;
- using System.IO;
- public class CryptoService
- {
- /// <summary>
- /// 加密的密钥
- /// </summary>
- string sKey = "22362E7A9285DD53A0BBC2932F9733C505DC04EDBFE00D70";
- string sIV = "1E7FA9231E7FA923";
- byte[] byteKey;
- byte[] byteIV;
- /// <summary>
- /// 加密向量
- /// </summary>
- static byte[] bIV ={ 1, 2, 3, 4, 5, 6, 7, 8 };
- public CryptoService()
- { }
- public CryptoService(string key, string IV)
- {
- sKey = key;
- sIV = IV;
- byteKey = CryptoHelper.HexStringToByteArray(sKey);
- byteIV = CryptoHelper.HexStringToByteArray(sIV);
- }
- /// <summary>
- /// 将明文加密,返回密文
- /// </summary>
- /// <param name="Data">要加密的字串</param>
- /// <returns></returns>
- public byte[] Encrypt(string Data)
- {
- try
- {
- byte[] ret;
- using (MemoryStream mStream = new MemoryStream())
- using (CryptoStream cStream = new CryptoStream(mStream,
- new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),
- CryptoStreamMode.Write))
- {
- byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);
- // Write the byte array to the crypto stream and flush it.
- cStream.Write(toEncrypt, 0, toEncrypt.Length);
- cStream.FlushFinalBlock();
- // Get an array of bytes from the
- // MemoryStream that holds the
- // encrypted data.
- ret = mStream.ToArray();
- }
- return ret;
- }
- catch (CryptographicException e)
- {
- //Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
- return null;
- }
- }
- /// <summary>
- /// 将明文加密,返回密文
- /// </summary>
- /// <param name="toEncrypt">明文</param>
- /// <param name="encrypted">密文</param>
- /// <returns></returns>
- public bool Encrypt(byte[] toEncrypt, out byte[] encrypted)
- {
- encrypted = null;
- try
- {
- // Create a new MemoryStream using the passed
- // array of encrypted data.
- // Create a CryptoStream using the MemoryStream
- // and the passed key and initialization vector (IV).
- using (MemoryStream mStream = new MemoryStream())
- using (CryptoStream cStream = new CryptoStream(mStream,
- new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),
- CryptoStreamMode.Write))
- {
- // Write the byte array to the crypto stream and flush it.
- cStream.Write(toEncrypt, 0, toEncrypt.Length);
- cStream.FlushFinalBlock();
- // Get an array of bytes from the
- // MemoryStream that holds the
- // encrypted data.
- encrypted = mStream.ToArray();
- }
- return true;
- }
- catch (CryptographicException e)
- {
- //Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
- return false;
- }
- }
- /// <summary>
- /// 将明文加密,返回 Base64 字符串
- /// </summary>
- /// <param name="Data"></param>
- /// <returns></returns>
- public string EncryptToString(string Data)
- {
- try
- {
- string base64String = string.Empty;
- using (MemoryStream mStream = new MemoryStream())
- using (CryptoStream cStream = new CryptoStream(mStream,
- new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),
- CryptoStreamMode.Write))
- {
- byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);
- cStream.Write(toEncrypt, 0, toEncrypt.Length);
- cStream.FlushFinalBlock();
- byte[] ret = mStream.ToArray();
- base64String = Convert.ToBase64String(ret);
- }
- return base64String;
- }
- catch (CryptographicException e)
- {
- return null;
- }
- }
- /// <summary>
- /// 将密文解密,返回明文
- /// </summary>
- /// <param name="Data">密文</param>
- /// <returns>明文</returns>
- public bool Decrypt(byte[] Data, out string decrypted)
- {
- decrypted = string.Empty;
- try
- {
- using (MemoryStream msDecrypt = new MemoryStream(Data))
- using (CryptoStream csDecrypt = new CryptoStream(msDecrypt,
- new TripleDESCryptoServiceProvider().CreateDecryptor(byteKey, byteIV),
- CryptoStreamMode.Read))
- {
- byte[] fromEncrypt = new byte[Data.Length];
- // Read the decrypted data out of the crypto stream
- // and place it into the temporary buffer.
- csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
- decrypted = Encoding.UTF8.GetString(fromEncrypt);//new ASCIIEncoding().GetString(fromEncrypt);
- return true;
- }
- }
- catch (CryptographicException e)
- {
- return false;
- }
- }
- }
PostService.cs
- using System;
- using System.Collections.Generic;
- using System.Text;
- public class PostService
- {
- private System.Collections.Specialized.NameValueCollection Inputs = new System.Collections.Specialized.NameValueCollection();
- public string Url = "";
- public string Method = "post";
- public string FormName = "form1";
- /// <summary>
- /// 添加需要提交的名和值
- /// </summary>
- /// <param name="name"></param>
- /// <param name="value"></param>
- public void Add(string name, string value)
- {
- Inputs.Add(name, value);
- }
- /// <summary>
- /// 以输出Html方式POST
- /// </summary>
- public void Post()
- {
- System.Web.HttpContext.Current.Response.Clear();
- string html = string.Empty;
- html += ("<html><head>");
- html += (string.Format("</head><body onload=/"document.{0}.submit()/">", FormName));
- html += (string.Format("<form name=/"{0}/" method=/"{1}/" action=/"{2}/" >", FormName, Method, Url));
- try
- {
- for (int i = 0; i < Inputs.Keys.Count; i++)
- {
- html += (string.Format("<input name=/"{0}/" type=/"hidden/" value=/"{1}/">", Inputs.Keys[i], Inputs[Inputs.Keys[i]]));
- }
- html += ("</form>");
- html += ("</body></html>");
- System.Web.HttpContext.Current.Response.Write(html);
- System.Web.HttpContext.Current.Response.End();
- }
- catch (Exception ee)
- {
- //
- }
- }
- }
SSORequest.cs
- using System;
- using System.Data;
- using System.Configuration;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- [Serializable]
- public class SSORequest : MarshalByRefObject
- {
- public string IASID; //各独立站点标识ID
- public string TimeStamp; //时间戳
- public string AppUrl; //各独立站点的访问地址
- public string Authenticator; //各独立站点的 Token
- public string UserAccount; //账号
- public string Password; //密码
- public string IPAddress; //IP地址
- //为ssresponse对象做准备
- public string ErrorDescription = "认证失败"; //用户认证通过,认证失败,包数据格式不正确,数据校验不正确
- public int Result = -1;
- public SSORequest()
- {
- }
- /// <summary>
- /// 获取当前页面上的SSORequest对象
- /// </summary>
- /// <param name="CurrentPage"></param>
- /// <returns></returns>
- public static SSORequest GetRequest(Page CurrentPage)
- {
- SSORequest request = new SSORequest();
- request.IPAddress = CurrentPage.Request.UserHostAddress;
- request.IASID = CurrentPage.Request["IASID"].ToString();// Request本身会Decode
- request.UserAccount = CurrentPage.Request["UserAccount"].ToString();//this.Text
- request.Password = CurrentPage.Request["Password"].ToString();
- request.AppUrl = CurrentPage.Request["AppUrl"].ToString();
- request.Authenticator = CurrentPage.Request["Authenticator"].ToString();
- request.TimeStamp = CurrentPage.Request["TimeStamp"].ToString();
- return request;
- }
- }
配置web.config
- <authentication mode="Forms">
- <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="60">
- </forms>
- </authentication>
- <authorization>
- <!--拒绝所有匿名用户-->
- <deny users="?"/>
- </authorization>
最后效果如下:登录总站后,各站点之间无需再登录,可以互相访问。
另外,注销登录后,访问站点1 http://localhost/Site1/Default.aspx ,会自动跳转到主站登录页面 http://localhost/MasterSite/Default.aspx ,同样访问站点2 http://localhost/Site2/Default.aspx 也会转到主站登录页面。从主站登录后,分别访问站点1和站点2。
在IIS配置虚拟目录MasterSite Site1 Site2,当然你也可以新建站点MasterSite Site1 Site2,修改hosts表
127.0.0.1 www.MasterSite.com
127.0.0.1 www.Site1.com
127.0.0.1 www.Site2.com