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、完成跨域单点登录。如 http://www.a.com/   http://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;
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.
12.public partial class _Default : System.Web.UI.Page
13.{
14.    protected void Page_Load(object sender, EventArgs e)
15.    {
16.        if (!IsPostBack)
17.        {
18.            SSORequest ssoRequest = new SSORequest();
19.
20.
21.            #region 验证 Post 过来的参数
22.            //--------------------------------
23.            // 请求注销
24.            if (!string.IsNullOrEmpty(Request["Logout"]))
25.            {
26.                Authentication.Logout();
27.                return;
28.            }
29.            //--------------------------------
30.            // 各独立站点标识
31.            if (string.IsNullOrEmpty(Request["IASID"]))
32.            {
33.                return;
34.            }
35.            else
36.            {
37.                ssoRequest.IASID = Request["IASID"];
38.            }
39.
40.            //--------------------------------
41.            // 时间戳
42.            if (string.IsNullOrEmpty(Request["TimeStamp"]))
43.            {
44.                return;
45.            }
46.            else
47.            {
48.                ssoRequest.TimeStamp = Request["TimeStamp"];
49.            }
50.
51.            //--------------------------------
52.            // 各独立站点的访问地址
53.            if (string.IsNullOrEmpty(Request["AppUrl"]))
54.            {
55.                return;
56.            }
57.            else
58.            {
59.                ssoRequest.AppUrl = Request["AppUrl"];
60.            }
61.
62.            //--------------------------------
63.            // 各独立站点的 Token
64.            if (string.IsNullOrEmpty(Request["Authenticator"]))
65.            {
66.                return;
67.            }
68.            else
69.            {
70.                ssoRequest.Authenticator = Request["Authenticator"];
71.            }
72.
73.            ViewState["SSORequest"] = ssoRequest;
74.
75.            #endregion
76.
77.
78.            //验证从分站发过来的Token
79.            if (Authentication.ValidateAppToken(ssoRequest))
80.            {
81.                string userAccount = null;
82.
83.                // 验证用户之前是否登录过
84.                //验证 EAC 认证中心的 Cookie,验证通过时获取用户登录账号
85.                if (Authentication.ValidateEACCookie(out userAccount))
86.                {
87.                    ssoRequest.UserAccount = userAccount;
88.
89.                    //创建认证中心发往各分站的 Token
90.                    if (Authentication.CreateEACToken(ssoRequest))
91.                    {
92.                        Post(ssoRequest);
93.                    }
94.                }
95.                else
96.                {
97.                    return;
98.                }
99.            }
100.            else
101.            {
102.                return;
103.            }
104.        }
105.    }
106.
107.
108.    //post请求
109.    void Post(SSORequest ssoRequest)
110.    {
111.        PostService ps = new PostService();
112.
113.        ps.Url = ssoRequest.AppUrl;
114.
115.        ps.Add("UserAccount", ssoRequest.UserAccount);
116.        ps.Add("IASID", ssoRequest.IASID);
117.        ps.Add("TimeStamp", ssoRequest.TimeStamp);
118.        ps.Add("AppUrl", ssoRequest.AppUrl);
119.        ps.Add("Authenticator", ssoRequest.Authenticator);
120.
121.        ps.Post();
122.    }
123.
124.    /// <summary>
125.    /// 验证登录账号和密码是否正确
126.    /// </summary>
127.    /// <param name="userName">登录账号</param>
128.    /// <param name="userPwd">登录密码</param>
129.    /// <returns></returns>
130.    private bool ValidateUserInfo(string userName, string userPwd)
131.    {
132.        //从数据库中读取,验证登录账号和密码
133.        //略...
134.        return true;
135.    }
136.
137.    protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
138.    {
139.        if (string.IsNullOrEmpty(Login1.UserName) || string.IsNullOrEmpty(Login1.Password))
140.        {
141.            Page.RegisterClientScriptBlock("Add", "<mce:script lanuage=\"javascript\"><!--
142.alert(‘用户名密码不能为空!‘);
143.// --></mce:script>");
144.            return;
145.        }
146.        else if (ValidateUserInfo(Login1.UserName, Login1.Password) == false)
147.        {
148.            Page.RegisterClientScriptBlock("Add", "<mce:script lanuage=\"javascript\"><!--
149.alert(‘用户名密码错误!‘);
150.// --></mce:script>");
151.            return;
152.        }
153.        else
154.        {
155.            Session["CurrUserName"] = Login1.UserName;
156.            Session.Timeout = 120;
157.
158.            SSORequest ssoRequest = ViewState["SSORequest"] as SSORequest;
159.
160.            // 如果不是从各分站 Post 过来的请求,则默认登录主站
161.            if (ssoRequest == null)
162.            {
163.                FormsAuthentication.SetAuthCookie(Login1.UserName, false);
164.
165.                ssoRequest = new SSORequest();
166.                //主站标识ID
167.                ssoRequest.IASID = "00";
168.                ssoRequest.AppUrl = "SiteList.aspx";
169.                ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
170.                ssoRequest.Authenticator = string.Empty;
171.
172.                Response.Redirect("SiteList.aspx");
173.            }
174.            ssoRequest.UserAccount = Login1.UserName;
175.
176.            //创建Token
177.            if (Authentication.CreateEACToken(ssoRequest))
178.            {
179.                string expireTime = DateTime.Now.AddHours(3).ToString("yyyy-MM-dd HH:mm");
180.
181.                Authentication.CreatEACCookie(ssoRequest.UserAccount, ssoRequest.TimeStamp, expireTime);
182.
183.                Post(ssoRequest);
184.            }
185.
186.        }
187.    }
188.
189.
190.}  

代码说明:验证分站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">
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.        <br />
13.        <br />
14.        <asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">返回主站</asp:LinkButton>
15.
16.        <asp:LinkButton ID="LinkButton2" runat="server" OnClick="LinkButton2_Click">注销登录</asp:LinkButton></div>
17.    </form>
18.</body>
19.</html>  

Default.cs code:

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.
12.public partial class _Default : System.Web.UI.Page
13.{
14.    protected void Page_Load(object sender, EventArgs e)
15.    {
16.        if (!IsPostBack)
17.        {
18.            #region SSO 部分代码
19.            SSORequest ssoRequest = new SSORequest();
20.
21.            if (string.IsNullOrEmpty(Request["IASID"]))
22.            {
23.                ssoRequest.IASID = "01";
24.                ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
25.                ssoRequest.AppUrl = Request.Url.ToString();
26.                Authentication.CreateAppToken(ssoRequest);
27.
28.                Post(ssoRequest);
29.            }
30.            else if (!string.IsNullOrEmpty(Request["IASID"])
31.                && !string.IsNullOrEmpty(Request["TimeStamp"])
32.                && !string.IsNullOrEmpty(Request["AppUrl"])
33.                && !string.IsNullOrEmpty(Request["UserAccount"])
34.                && !string.IsNullOrEmpty(Request["Authenticator"]))
35.            {
36.                ssoRequest.IASID = Request["IASID"];
37.                ssoRequest.TimeStamp = Request["TimeStamp"];
38.                ssoRequest.AppUrl = Request["AppUrl"];
39.                ssoRequest.UserAccount = Request["UserAccount"];
40.                ssoRequest.Authenticator = Request["Authenticator"];
41.
42.                if (Authentication.ValidateEACToken(ssoRequest))
43.                {
44.                    //从数据库中获取UserId
45.                    Session["CurrUserName"] = Request["UserAccount"];
46.                    Session.Timeout = 120;
47.                    FormsAuthentication.SetAuthCookie(Request["UserAccount"], false);
48.                    Response.Write(string.Format("{0},您好!欢迎来到site1,  >> 访问<a href="\" mce_href="\""http://localhost/Site2/Default.aspx\">site2</a>",ssoRequest.UserAccount));
49.                }
50.            }
51.
52.            ViewState["SSORequest"] = ssoRequest;
53.
54.            #endregion
55.        }
56.    }
57.
58.    void Post(SSORequest ssoRequest)
59.    {
60.        PostService ps = new PostService();
61.        //认证中心(主站)地址
62.        string EACUrl = "http://localhost/MasterSite/Default.aspx";
63.        ps.Url = EACUrl;
64.        //ps.Add("UserAccount", ssoRequest.UserAccount);
65.        ps.Add("IASID", ssoRequest.IASID);
66.        ps.Add("TimeStamp", ssoRequest.TimeStamp);
67.        ps.Add("AppUrl", ssoRequest.AppUrl);
68.        ps.Add("Authenticator", ssoRequest.Authenticator);70.        ps.Post();
71.    }
72.
73.
74.    //注销登录
75.    protected void LinkButton2_Click(object sender, EventArgs e)
76.    {
77.        FormsAuthentication.SignOut();
78.
79.        SSORequest ssoRequest = new SSORequest();
80.
81.        ssoRequest.IASID = "01";
82.        ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
83.        ssoRequest.AppUrl = Request.Url.ToString();
84.
85.        Authentication.CreateAppToken(ssoRequest);
86.
87.        PostService ps = new PostService();
88.
89.        //认证中心(主站)地址
90.        string EACUrl = "http://localhost/MasterSite/Default.aspx";
91.        ps.Url = EACUrl;
92.
93.        ps.Add("IASID", ssoRequest.IASID);
94.        ps.Add("TimeStamp", ssoRequest.TimeStamp);
95.        ps.Add("AppUrl", ssoRequest.AppUrl);
96.        ps.Add("Authenticator", ssoRequest.Authenticator);
97.
98.        ps.Add("Logout", "true");
99.
100.        ps.Post();
101.    }
102.
103.    //返回主站
104.    protected void LinkButton1_Click(object sender, EventArgs e)
105.    {
106.        if (Session["CurrUserName"] != null)
107.        {
108.            Response.Redirect("http://localhost/MasterSite/SiteList.aspx");
109.        }
110.    }
111.}  

配置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;
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.public partial class _Default : System.Web.UI.Page
12.{
13.    protected void Page_Load(object sender, EventArgs e)
14.    {
15.        if (!IsPostBack)
16.        {
17.            #region SSO 部分代码
18.            SSORequest ssoRequest = new SSORequest();
19.
20.            if (string.IsNullOrEmpty(Request["IASID"]))
21.            {
22.                ssoRequest.IASID = "02";
23.                ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
24.                ssoRequest.AppUrl = Request.Url.ToString();
25.                Authentication.CreateAppToken(ssoRequest);
26.
27.                Post(ssoRequest);
28.            }
29.            else if (!string.IsNullOrEmpty(Request["IASID"])
30.                && !string.IsNullOrEmpty(Request["TimeStamp"])
31.                && !string.IsNullOrEmpty(Request["AppUrl"])
32.                && !string.IsNullOrEmpty(Request["UserAccount"])
33.                && !string.IsNullOrEmpty(Request["Authenticator"]))
34.            {
35.                ssoRequest.IASID = Request["IASID"];
36.                ssoRequest.TimeStamp = Request["TimeStamp"];
37.                ssoRequest.AppUrl = Request["AppUrl"];
38.                ssoRequest.UserAccount = Request["UserAccount"];
39.                ssoRequest.Authenticator = Request["Authenticator"];
40.
41.                if (Authentication.ValidateEACToken(ssoRequest))
42.                {
43.                    Session["CurrUserName"] = Request["UserAccount"];
44.                    Session.Timeout = 120;
45.                    FormsAuthentication.SetAuthCookie(Request["UserAccount"], false);
46.                    Response.Write(string.Format("{0},您好!欢迎来到site2,  >> 访问<a href="\" mce_href="\""http://localhost/Site1/Default.aspx\">site1</a>", ssoRequest.UserAccount));
47.                }
48.            }
49.
50.            ViewState["SSORequest"] = ssoRequest;
51.
52.            #endregion
53.        }
54.    }
55.
56.    void Post(SSORequest ssoRequest)
57.    {
58.        PostService ps = new PostService();
59.        //认证中心(主站)地址
60.        string EACUrl = "http://localhost/MasterSite/Default.aspx";
61.        ps.Url = EACUrl;
62.        //ps.Add("UserAccount", ssoRequest.UserAccount);
63.        ps.Add("IASID", ssoRequest.IASID);
64.        ps.Add("TimeStamp", ssoRequest.TimeStamp);
65.        ps.Add("AppUrl", ssoRequest.AppUrl);
66.        ps.Add("Authenticator", ssoRequest.Authenticator);
67.
68.        ps.Post();
69.    }
70.
71.
72.    //注销登录
73.    protected void LinkButton2_Click(object sender, EventArgs e)
74.    {
75.        FormsAuthentication.SignOut();
76.
77.        SSORequest ssoRequest = new SSORequest();
78.
79.        ssoRequest.IASID = "02";
80.        ssoRequest.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
81.        ssoRequest.AppUrl = Request.Url.ToString();
82.
83.        Authentication.CreateAppToken(ssoRequest);
84.
85.        PostService ps = new PostService();
86.
87.        //认证中心(主站)地址
88.        string EACUrl = "http://localhost/MasterSite/Default.aspx";
89.        ps.Url = EACUrl;
90.
91.        ps.Add("IASID", ssoRequest.IASID);
92.        ps.Add("TimeStamp", ssoRequest.TimeStamp);
93.        ps.Add("AppUrl", ssoRequest.AppUrl);
94.        ps.Add("Authenticator", ssoRequest.Authenticator);
95.
96.        ps.Add("Logout", "true");
97.
98.        ps.Post();
99.    }
100.
101.    //返回主站
102.    protected void LinkButton1_Click(object sender, EventArgs e)
103.    {
104.        if (Session["CurrUserName"] != null)
105.        {
106.            Response.Redirect("http://localhost/MasterSite/SiteList.aspx");
107.        }
108.    }
109.} 

对于tokent请求,tokent验证,需要对它进行加密、解密。

其它代码:

Authentication.cs

1.using System;
2.using System.Data;
3.using System.Configuration;
4.using System.Web;
5.using System.Web.Security;
6.using System.Collections.Generic;
7.using System.Text;
8.
9./// <summary>
10./// 安全验证类
11./// </summary>
12.public class Authentication
13.{
14.    static readonly string cookieName = "EACToken";
15.    static readonly string hashSplitter = "|";
16.
17.    public Authentication()
18.    {
19.    }
20.
21.    public static string GetAppKey(int appID)
22.    {
23.        //string cmdText = @"select * from ";
24.        return string.Empty;
25.    }
26.
27.    public static string GetAppKey()
28.    {
29.        return "22362E7A9285DD53A0BBC2932F9733C505DC04EDBFE00D70";
30.    }
31.
32.    public static string GetAppIV()
33.    {
34.        return "1E7FA9231E7FA923";
35.    }
36.
37.    /// <summary>
38.    /// 取得加密服务
39.    /// </summary>
40.    /// <returns></returns>
41.    static CryptoService GetCryptoService()
42.    {
43.        string key = GetAppKey();
44.        string IV = GetAppIV();
45.
46.        CryptoService cs = new CryptoService(key, IV);
47.        return cs;
48.    }
49.
50.    /// <summary>
51.    /// 创建各分站发往认证中心的 Token
52.    /// </summary>
53.    /// <param name="ssoRequest"></param>
54.    /// <returns></returns>
55.    public static bool CreateAppToken(SSORequest ssoRequest)
56.    {
57.        string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
58.        string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
59.        string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
60.        byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
61.
62.        CryptoService cs = GetCryptoService();
63.
64.        byte[] encrypted;
65.
66.        if (cs.Encrypt(bToEncrypt, out encrypted))
67.        {
68.            ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
69.
70.            return true;
71.        }
72.        else
73.        {
74.            return false;
75.        }
76.    }
77.
78.
79.    /// <summary>
80.    /// 验证从各分站发送过来的 Token
81.    /// </summary>
82.    /// <param name="ssoRequest"></param>
83.    /// <returns></returns>
84.    public static bool ValidateAppToken(SSORequest ssoRequest)
85.    {
86.        string Authenticator = ssoRequest.Authenticator;
87.
88.        string OriginalAuthenticator = ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
89.        string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
90.        string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
91.        byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
92.
93.        CryptoService cs = GetCryptoService();
94.        byte[] encrypted;
95.
96.        if (cs.Encrypt(bToEncrypt, out encrypted))
97.        {
98.            return Authenticator == CryptoHelper.ToBase64String(encrypted);
99.        }
100.        else
101.        {
102.            return false;
103.        }
104.    }
105.
106.
107.    /// <summary>
108.    /// 创建认证中心发往各分站的 Token
109.    /// </summary>
110.    /// <param name="ssoRequest"></param>
111.    /// <returns></returns>
112.    public static bool CreateEACToken(SSORequest ssoRequest)
113.    {
114.        string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
115.        string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
116.        string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
117.        byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
118.
119.        CryptoService cs = GetCryptoService();
120.        byte[] encrypted;
121.
122.        if (cs.Encrypt(bToEncrypt, out encrypted))
123.        {
124.            ssoRequest.Authenticator = CryptoHelper.ToBase64String(encrypted);
125.
126.            return true;
127.        }
128.        else
129.        {
130.            return false;
131.        }
132.    }
133.
134.
135.    /// <summary>
136.    /// 验证从认证中心发送过来的 Token
137.    /// </summary>
138.    /// <param name="ssoRequest"></param>
139.    /// <returns></returns>
140.    public static bool ValidateEACToken(SSORequest ssoRequest)
141.    {
142.        string Authenticator = ssoRequest.Authenticator;
143.
144.        string OriginalAuthenticator = ssoRequest.UserAccount + ssoRequest.IASID + ssoRequest.TimeStamp + ssoRequest.AppUrl;
145.        string AuthenticatorDigest = CryptoHelper.ComputeHashString(OriginalAuthenticator);
146.        string sToEncrypt = OriginalAuthenticator + AuthenticatorDigest;
147.        byte[] bToEncrypt = CryptoHelper.ConvertStringToByteArray(sToEncrypt);
148.
149.        string EncryCurrentAuthenticator = string.Empty;
150.        CryptoService cs = GetCryptoService();
151.        byte[] encrypted;
152.
153.        if (cs.Encrypt(bToEncrypt, out encrypted))
154.        {
155.            EncryCurrentAuthenticator = CryptoHelper.ToBase64String(encrypted);
156.
157.            return Authenticator == EncryCurrentAuthenticator;
158.        }
159.        else
160.        {
161.            return false;
162.        }
163.    }
164.
165.
166.    /// <summary>
167.    /// 创建 EAC 认证中心的 Cookie
168.    /// </summary>
169.    /// <param name="userAccount"></param>
170.    /// <param name="timeStamp"></param>
171.    /// <param name="expireTime"></param>
172.    /// <param name="cookieValue"></param>
173.    /// <returns></returns>
174.    public static bool CreatEACCookie(string userAccount, string timeStamp, string expireTime)
175.    {
176.        string plainText = "UserAccount=" + userAccount + ";TimeStamp=" + timeStamp + ";ExpireTime=" + expireTime;
177.        plainText += hashSplitter + CryptoHelper.ComputeHashString(plainText);
178.
179.        CryptoService cs = GetCryptoService();
180.        byte[] encrypted;
181.
182.        if (cs.Encrypt(CryptoHelper.ConvertStringToByteArray(plainText), out encrypted))
183.        {
184.            string cookieValue = CryptoHelper.ToBase64String(encrypted);
185.            SetCookie(cookieValue);
186.
187.            return true;
188.        }
189.        else
190.        {
191.            return false;
192.        }
193.    }
194.
195.    /// <summary>
196.    /// 验证 EAC 认证中心的 Cookie,验证通过时获取用户登录账号
197.    /// </summary>
198.    /// <param name="userAccount">输出用户登录账号</param>
199.    /// <returns></returns>
200.    public static bool ValidateEACCookie(out string userAccount)
201.    {
202.        userAccount = string.Empty;
203.        try
204.        {
205.
206.            string cookieValue = GetCookie().Value;
207.            byte[] toDecrypt = CryptoHelper.FromBase64String(cookieValue);
208.            CryptoService cs = GetCryptoService();
209.
210.            string decrypted = string.Empty;
211.            if (cs.Decrypt(toDecrypt, out decrypted))
212.            {
213.
214.                string[] arrTemp = decrypted.Split(Convert.ToChar(hashSplitter));
215.                string plainText = arrTemp[0];
216.                string hashedText = arrTemp[1];
217.
218.                userAccount = plainText.Split(Convert.ToChar(";"))[0].Split(Convert.ToChar("="))[1];
219.
220.                return hashedText.Replace("\0", string.Empty) == CryptoHelper.ComputeHashString(plainText);
221.
222.            }
223.            else
224.            {
225.                return false;
226.            }
227.        }
228.        catch (Exception e)
229.        {
230.            return false;
231.        }
232.    }
233.
234.
235.    public static void Logout()
236.    {
237.        HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Parse("1900-1-1");
238.        HttpContext.Current.Response.Cookies[cookieName].Path = "/";
239.    }
240.
241.    private static void SetCookie(string cookieValue)
242.    {
243.        HttpContext.Current.Response.Cookies[cookieName].Value = cookieValue;
244.        HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Now.AddHours(24);
245.        HttpContext.Current.Response.Cookies[cookieName].Path = "/";
246.    }
247.
248.    private static HttpCookie GetCookie()
249.    {
250.        HttpCookie cookie = HttpContext.Current.Request.Cookies["EACToken"];
251.        return cookie;
252.    }
253.} 

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>  

<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      http://www.mastersite.com/

127.0.0.1      http://www.site1.com/

127.0.0.1      http://www.site2.com/

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

时间: 2024-10-06 01:09:08

asp.net 跨域单点登录 【转】的相关文章

asp.net 真正实现完全跨域单点登录

单点登录(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

跨域单点登录系统的设计与实现

跨域单点登录系统的设计与实现 一.跨域单点登录系统整体设计 1. 系统架构 如上图所示:在系统存在一个认证中心以及多个站点.用户信息统一由认证中心管理,在其它子站的登录均会跳转到认证中心来登录. 2. 工作流程 单点登录系统的关键在于,当用户从一个子站登录后,它会在认证中心生成ticket标识,只要该标识存在就代表用户已经成功登陆了.每个子站在进入之前,无论本地ticket标识是否存在,均会去请求一次认证中心,要做的事情如下:如果子站ticket不存在,并不一定代表用户没有从别的子站登录,但是如

使用Cookie实现跨域单点登录的原理

对于构建分布式系统来说业务功能的物理部署会随着新的业务模块的增加而增加或改变物理部署的位置.而每个用户都有统一的帐号作为我们登录系统时的一个认证.当应用程序部署在不同的物理机上,我们去访问不同的业务功能时,需要再次登录并记录每个业务对应的用户名和密码,这样会造成很大的麻烦,耽误工作效率,浪费很多时间.这种情况如果我们不引入CAS单点跨域登录原理,影响信息化给我们带来的便捷性和高效性,也会影响一定的用户体验. CAS跨域单点登录原理实现思想如下图更能清晰的描绘出来,我们来看看吧!

Cookie同域,跨域单点登录(转)

Cookie 同域单点登录 最近在做一个单点登录的系统整合项目,之前我们使用控件实现单点登录(以后可以介绍一下).但现在为了满足客户需求,在不使用控件情况下实现单点登录,先来介绍一下单点登录. 单点登录:多个不同系统整合到统一加载个平台,用户在任何一个系统登录后,可以访问这个统一加载上的所有系统.登录之后,用户的权限和信息不再受某个系统的限制,即使某个系统出现故障(包括统一加载平台),其他系统还是能正常使用的.这就需要用户权限等信息保存到客户端,不受服务器的限制. 在cookie相关文档信息中,

B/S系统间跨域单点登录设计思路

基于B/S系统间单点登录 此处说的单点登录的概念,即不同系统公用一个登录界面.一处系统通过登录验证,在接入的各系统均为登录状态.一般有两种情景: 1)  一级域名相同 例如:tieba.baidu.com 和 www.baidu.com 这种情形的解决方案,非常简单.就是在统一登录页面登录成功以后,将用户的token(共享的session)信息存在cookie里,且cookie的作用域设为一级域名,例如设为baidu.com.这样同一个浏览器就实现了用户登录信息的共享. 2)  一级域名不相同

如何在多台服务器上共享Session(PHP/JSP/ASP.NET)以及单点登录(SSO)

如何在多台服务器上共享Session(PHP/JSP/ASP.NET)以及单点登录(SSO) Apache Session复制: http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html 使用Memcached来共享PHP Session: https://www.digitalocean.com/community/tutorials/how-to-share-php-sessions-on-multiple-memcached-se

JAVA实现同域单点登录

所用技术: SSM MySQL Maven Tomcat8.0 同域单点登录详细步骤如下: 1.首先写一个登录界面(隐藏域为暂存地址) 2.判断用户密码是否正确,正确则添加cookie,否则返回错误页面 3.编写登录校验接口 4.编写两个同域应用 cookie没有设置时间默认浏览器关闭消失 效果实现步骤: 1.打开两个浏览器 2.访问Demo1及Demo2 3.此时因没有登录都会进入登录界面 4.登录Demo1 5.再到Demo2刷新页面 此时发现Demo2没有登录就进到了主界面,同域单点登录实

ASP.NET实现SSO单点登录

利用ASP.NET Forms身份认证轻轻松松实现单点登录 比如我们的主域名是domain.com 其他的二级域名有 1.list.domain.com 2.item.domain.com 3.home.domain.com 登录和注册都放在passport.domain.com这个二级域名下去处理 在Web.config中配置 1 <authentication mode="Forms"> 4 <forms name="CNBDQ" loginU

思道OA之ASP.NET OA系统单点登录集成技术

思道OA开发版支持第三方集成,可以第三方的各种管理系统.校园数字化系统.统一认证,进行单点集成登录. (一)第三方系统单点登录到OA系统 下载源码 步骤1: web.config添加以下代码,允许匿名用户访问/sso.aspx,默认开发版已经添加, 将sso.aspx放置到OA目录Webroot下. <location path="sso.aspx"> <system.web> <authorization> <allow users=&quo