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登录验证。
      配置如下:

     

  1. <authentication mode="Forms">  
  2.   <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="120">  
  3.   </forms>  
  4. </authentication>  
  5. <authorization>  
  6.     <!--拒绝所有匿名用户-->  
  7.     <deny users="?"/>  
  8. </authorization>  

      添加Default.aspx页面,用来进行登录。代码如下:
   

     HTML Code:

    

  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>  
  2.   
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  4.   
  5. <html xmlns="http://www.w3.org/1999/xhtml" >  
  6. <head runat="server">  
  7.     <title>总站登录</title>  
  8. </head>  
  9. <body>  
  10.     <form id="form1" runat="server">  
  11.     <div>  
  12.         <asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate" UserName="test">  
  13.         </asp:Login>  
  14.     </div>  
  15.     </form>  
  16. </body>  
  17. </html>  


   Default.cs Code:

  

  1. using System;  
  2. 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:

  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>  
  2.   
  3. <!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:

  1. using System;  
  2. 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

  1. <authentication mode="Forms">  
  2.             <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="60">  
  3.             </forms>  
  4.         </authentication>  
  5.         <authorization>  
  6.             <!--拒绝所有匿名用户-->  
  7.             <deny users="?"/>  
  8.         </authorization>  

三、同二一样,新建站点Site2,代码如下:

  1. using System;  
  2. 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

  1. using System;  
  2. 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

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Security.Cryptography;  
  5.   
  6. public class CryptoHelper  
  7. {  
  8.     /// <summary>   
  9.     /// 复合 Hash:string --> byte[] --> hashed byte[] --> base64 string   
  10.     /// </summary>   
  11.     /// <param name="s"></param>   
  12.     /// <returns></returns>   
  13.     public static string ComputeHashString(string s)  
  14.     {  
  15.         return ToBase64String(ComputeHash(ConvertStringToByteArray(s)));  
  16.     }  
  17.   
  18.   
  19.     public static byte[] ComputeHash(byte[] buf)  
  20.     {  
  21.         //return ((HashAlgorithm)CryptoConfig.CreateFromName("SHA1")).ComputeHash(buf);   
  22.         return SHA1.Create().ComputeHash(buf);  
  23.   
  24.     }  
  25.   
  26.     /// <summary>   
  27.     /// //System.Convert.ToBase64String   
  28.     /// </summary>   
  29.     /// <param name="buf"></param>   
  30.     /// <returns></returns>   
  31.     public static string ToBase64String(byte[] buf)  
  32.     {  
  33.         return System.Convert.ToBase64String(buf);  
  34.     }  
  35.   
  36.   
  37.     public static byte[] FromBase64String(string s)  
  38.     {  
  39.         return System.Convert.FromBase64String(s);  
  40.     }  
  41.   
  42.     /// <summary>   
  43.     /// //Encoding.UTF8.GetBytes(s)   
  44.     /// </summary>   
  45.     /// <param name="s"></param>   
  46.     /// <returns></returns>   
  47.     public static byte[] ConvertStringToByteArray(String s)  
  48.     {  
  49.         return Encoding.UTF8.GetBytes(s);//gb2312   
  50.     }  
  51.   
  52.   
  53.     public static string ConvertByteArrayToString(byte[] buf)  
  54.     {  
  55.         //return System.Text.Encoding.GetEncoding("utf-8").GetString(buf);   
  56.   
  57.         return Encoding.UTF8.GetString(buf);  
  58.     }  
  59.   
  60.   
  61.     /// <summary>   
  62.     /// 字节数组转换为十六进制字符串   
  63.     /// </summary>   
  64.     /// <param name="buf"></param>   
  65.     /// <returns></returns>   
  66.     public static string ByteArrayToHexString(byte[] buf)  
  67.     {  
  68.         StringBuilder sb = new StringBuilder();  
  69.         for (int i = 0; i < buf.Length; i++)  
  70.         {  
  71.             sb.Append(buf[i].ToString("X").Length == 2 ? buf[i].ToString("X") : "0" + buf[i].ToString("X"));  
  72.         }  
  73.         return sb.ToString();  
  74.     }  
  75.   
  76.     /// <summary>   
  77.     /// 十六进制字符串转换为字节数组   
  78.     /// </summary>   
  79.     /// <param name="s"></param>   
  80.     /// <returns></returns>   
  81.     public static byte[] HexStringToByteArray(string s)  
  82.     {  
  83.         Byte[] buf = new byte[s.Length / 2];  
  84.         for (int i = 0; i < buf.Length; i++)  
  85.         {  
  86.             buf[i] = (byte)(Char2Hex(s.Substring(i * 2, 1)) * 0x10 + Char2Hex(s.Substring(i * 2 + 1, 1)));  
  87.         }  
  88.         return buf;  
  89.     }  
  90.   
  91.   
  92.     private static byte Char2Hex(string chr)  
  93.     {  
  94.         switch (chr)  
  95.         {  
  96.             case "0":  
  97.                 return 0x00;  
  98.             case "1":  
  99.                 return 0x01;  
  100.             case "2":  
  101.                 return 0x02;  
  102.             case "3":  
  103.                 return 0x03;  
  104.             case "4":  
  105.                 return 0x04;  
  106.             case "5":  
  107.                 return 0x05;  
  108.             case "6":  
  109.                 return 0x06;  
  110.             case "7":  
  111.                 return 0x07;  
  112.             case "8":  
  113.                 return 0x08;  
  114.             case "9":  
  115.                 return 0x09;  
  116.             case "A":  
  117.                 return 0x0a;  
  118.             case "B":  
  119.                 return 0x0b;  
  120.             case "C":  
  121.                 return 0x0c;  
  122.             case "D":  
  123.                 return 0x0d;  
  124.             case "E":  
  125.                 return 0x0e;  
  126.             case "F":  
  127.                 return 0x0f;  
  128.         }  
  129.         return 0x00;  
  130.     }  
  131. }  

CryptoService.cs

  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Web;  
  5. using System.Web.Security;  
  6. using System.Web.UI;  
  7. using System.Web.UI.WebControls;  
  8. using System.Web.UI.WebControls.WebParts;  
  9. using System.Web.UI.HtmlControls;  
  10. using System.Text;  
  11. using System.Security.Cryptography;  
  12. using System.IO;  
  13.   
  14. public class CryptoService  
  15. {  
  16.     /// <summary>   
  17.     /// 加密的密钥   
  18.     /// </summary>   
  19.     string sKey = "22362E7A9285DD53A0BBC2932F9733C505DC04EDBFE00D70";  
  20.     string sIV = "1E7FA9231E7FA923";  
  21.   
  22.     byte[] byteKey;  
  23.     byte[] byteIV;  
  24.   
  25.     /// <summary>   
  26.     /// 加密向量   
  27.     /// </summary>   
  28.     static byte[] bIV ={ 1, 2, 3, 4, 5, 6, 7, 8 };  
  29.   
  30.     public CryptoService()  
  31.     { }  
  32.   
  33.     public CryptoService(string key, string IV)  
  34.     {  
  35.         sKey = key;  
  36.         sIV = IV;  
  37.   
  38.         byteKey = CryptoHelper.HexStringToByteArray(sKey);  
  39.         byteIV = CryptoHelper.HexStringToByteArray(sIV);  
  40.     }  
  41.   
  42.   
  43.   
  44.     /// <summary>   
  45.     /// 将明文加密,返回密文   
  46.     /// </summary>   
  47.     /// <param name="Data">要加密的字串</param>   
  48.     /// <returns></returns>   
  49.     public byte[] Encrypt(string Data)  
  50.     {  
  51.         try  
  52.         {  
  53.             byte[] ret;  
  54.   
  55.             using (MemoryStream mStream = new MemoryStream())  
  56.             using (CryptoStream cStream = new CryptoStream(mStream,  
  57.                 new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),  
  58.                 CryptoStreamMode.Write))  
  59.             {  
  60.   
  61.                 byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);  
  62.   
  63.                 // Write the byte array to the crypto stream and flush it.   
  64.                 cStream.Write(toEncrypt, 0, toEncrypt.Length);  
  65.                 cStream.FlushFinalBlock();  
  66.   
  67.                 // Get an array of bytes from the    
  68.                 // MemoryStream that holds the    
  69.                 // encrypted data.   
  70.                 ret = mStream.ToArray();  
  71.   
  72.             }  
  73.   
  74.             return ret;  
  75.         }  
  76.         catch (CryptographicException e)  
  77.         {  
  78.             //Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);   
  79.             return null;  
  80.         }  
  81.   
  82.     }  
  83.   
  84.   
  85.     /// <summary>   
  86.     /// 将明文加密,返回密文   
  87.     /// </summary>   
  88.     /// <param name="toEncrypt">明文</param>   
  89.     /// <param name="encrypted">密文</param>   
  90.     /// <returns></returns>   
  91.     public bool Encrypt(byte[] toEncrypt, out byte[] encrypted)  
  92.     {  
  93.         encrypted = null;  
  94.         try  
  95.         {  
  96.             // Create a new MemoryStream using the passed    
  97.             // array of encrypted data.   
  98.             // Create a CryptoStream using the MemoryStream    
  99.             // and the passed key and initialization vector (IV).   
  100.             using (MemoryStream mStream = new MemoryStream())  
  101.             using (CryptoStream cStream = new CryptoStream(mStream,  
  102.                 new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),  
  103.                 CryptoStreamMode.Write))  
  104.             {  
  105.   
  106.                 // Write the byte array to the crypto stream and flush it.   
  107.                 cStream.Write(toEncrypt, 0, toEncrypt.Length);  
  108.                 cStream.FlushFinalBlock();  
  109.   
  110.                 // Get an array of bytes from the    
  111.                 // MemoryStream that holds the    
  112.                 // encrypted data.   
  113.                 encrypted = mStream.ToArray();  
  114.             }  
  115.   
  116.             return true;  
  117.         }  
  118.         catch (CryptographicException e)  
  119.         {  
  120.             //Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);   
  121.             return false;  
  122.         }  
  123.   
  124.     }  
  125.   
  126.   
  127.   
  128.     /// <summary>   
  129.     /// 将明文加密,返回 Base64 字符串   
  130.     /// </summary>   
  131.     /// <param name="Data"></param>   
  132.     /// <returns></returns>   
  133.     public string EncryptToString(string Data)  
  134.     {  
  135.         try  
  136.         {  
  137.             string base64String = string.Empty;  
  138.   
  139.             using (MemoryStream mStream = new MemoryStream())  
  140.             using (CryptoStream cStream = new CryptoStream(mStream,  
  141.                 new TripleDESCryptoServiceProvider().CreateEncryptor(byteKey, byteIV),  
  142.                 CryptoStreamMode.Write))  
  143.             {  
  144.   
  145.                 byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);  
  146.   
  147.                 cStream.Write(toEncrypt, 0, toEncrypt.Length);  
  148.                 cStream.FlushFinalBlock();  
  149.   
  150.                 byte[] ret = mStream.ToArray();  
  151.   
  152.                 base64String = Convert.ToBase64String(ret);  
  153.             }  
  154.   
  155.             return base64String;  
  156.         }  
  157.         catch (CryptographicException e)  
  158.         {  
  159.             return null;  
  160.         }  
  161.   
  162.     }  
  163.   
  164.   
  165.     /// <summary>   
  166.     /// 将密文解密,返回明文   
  167.     /// </summary>   
  168.     /// <param name="Data">密文</param>   
  169.     /// <returns>明文</returns>   
  170.     public bool Decrypt(byte[] Data, out string decrypted)  
  171.     {  
  172.         decrypted = string.Empty;  
  173.         try  
  174.         {  
  175.   
  176.             using (MemoryStream msDecrypt = new MemoryStream(Data))  
  177.             using (CryptoStream csDecrypt = new CryptoStream(msDecrypt,  
  178.                 new TripleDESCryptoServiceProvider().CreateDecryptor(byteKey, byteIV),  
  179.                 CryptoStreamMode.Read))  
  180.             {  
  181.   
  182.                 byte[] fromEncrypt = new byte[Data.Length];  
  183.   
  184.                 // Read the decrypted data out of the crypto stream   
  185.                 // and place it into the temporary buffer.   
  186.                 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);  
  187.   
  188.                 decrypted = Encoding.UTF8.GetString(fromEncrypt);//new ASCIIEncoding().GetString(fromEncrypt);   
  189.   
  190.                 return true;  
  191.             }  
  192.         }  
  193.         catch (CryptographicException e)  
  194.         {  
  195.             return false;  
  196.         }  
  197.     }  
  198.   
  199. }  

  

PostService.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.   
  5. public class PostService  
  6. {  
  7.     private System.Collections.Specialized.NameValueCollection Inputs = new System.Collections.Specialized.NameValueCollection();  
  8.     public string Url = "";  
  9.     public string Method = "post";  
  10.     public string FormName = "form1";  
  11.   
  12.     /// <summary>   
  13.     /// 添加需要提交的名和值   
  14.     /// </summary>   
  15.     /// <param name="name"></param>   
  16.     /// <param name="value"></param>   
  17.     public void Add(string name, string value)  
  18.     {  
  19.         Inputs.Add(name, value);  
  20.     }  
  21.   
  22.     /// <summary>   
  23.     /// 以输出Html方式POST   
  24.     /// </summary>   
  25.     public void Post()  
  26.     {  
  27.         System.Web.HttpContext.Current.Response.Clear();  
  28.   
  29.         string html = string.Empty;  
  30.   
  31.         html += ("<html><head>");  
  32.         html += (string.Format("</head><body onload=/"document.{0}.submit()/">", FormName));  
  33.         html += (string.Format("<form name=/"{0}/" method=/"{1}/" action=/"{2}/" >", FormName, Method, Url));  
  34.         try  
  35.         {  
  36.             for (int i = 0; i < Inputs.Keys.Count; i++)  
  37.             {  
  38.                 html += (string.Format("<input name=/"{0}/" type=/"hidden/" value=/"{1}/">", Inputs.Keys[i], Inputs[Inputs.Keys[i]]));  
  39.             }  
  40.             html += ("</form>");  
  41.             html += ("</body></html>");  
  42.   
  43.             System.Web.HttpContext.Current.Response.Write(html);  
  44.             System.Web.HttpContext.Current.Response.End();  
  45.         }  
  46.         catch (Exception ee)  
  47.         {  
  48.             //   
  49.         }  
  50.     }  
  51. }  

SSORequest.cs

  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Web;  
  5. using System.Web.Security;  
  6. using System.Web.UI;  
  7. using System.Web.UI.WebControls;  
  8. using System.Web.UI.WebControls.WebParts;  
  9. using System.Web.UI.HtmlControls;  
  10.   
  11. [Serializable]  
  12. public class SSORequest : MarshalByRefObject  
  13. {  
  14.     public string IASID;         //各独立站点标识ID   
  15.     public string TimeStamp;     //时间戳   
  16.     public string AppUrl;        //各独立站点的访问地址   
  17.     public string Authenticator; //各独立站点的 Token   
  18.   
  19.     public string UserAccount;   //账号   
  20.     public string Password;      //密码   
  21.   
  22.     public string IPAddress;     //IP地址   
  23.   
  24.     //为ssresponse对象做准备   
  25.     public string ErrorDescription = "认证失败";   //用户认证通过,认证失败,包数据格式不正确,数据校验不正确   
  26.     public int Result = -1;  
  27.   
  28.     public SSORequest()  
  29.     {  
  30.   
  31.     }  
  32.   
  33.   
  34.     /// <summary>   
  35.     /// 获取当前页面上的SSORequest对象   
  36.     /// </summary>   
  37.     /// <param name="CurrentPage"></param>   
  38.     /// <returns></returns>   
  39.     public static SSORequest GetRequest(Page CurrentPage)  
  40.     {  
  41.         SSORequest request = new SSORequest();  
  42.         request.IPAddress = CurrentPage.Request.UserHostAddress;  
  43.         request.IASID = CurrentPage.Request["IASID"].ToString();// Request本身会Decode   
  44.         request.UserAccount = CurrentPage.Request["UserAccount"].ToString();//this.Text   
  45.         request.Password = CurrentPage.Request["Password"].ToString();  
  46.         request.AppUrl = CurrentPage.Request["AppUrl"].ToString();  
  47.         request.Authenticator = CurrentPage.Request["Authenticator"].ToString();  
  48.         request.TimeStamp = CurrentPage.Request["TimeStamp"].ToString();  
  49.         return request;  
  50.     }  
  51. }  

  

配置web.config

  1. <authentication mode="Forms">  
  2.             <forms name=".AspxFormAuth" loginUrl="Default.aspx" defaultUrl="center.html" protection="All" path="/" timeout="60">  
  3.             </forms>  
  4.         </authentication>  
  5.         <authorization>  
  6.             <!--拒绝所有匿名用户-->  
  7.             <deny users="?"/>  
  8.         </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

源代码下载:http://download.csdn.net/source/1571879 

posted @ 2011-07-23 05:36  青衫  阅读(2032)  评论(2编辑  收藏  举报