单点登录问题

1.单点登录SSO实现原理:

多个客户端到统一的一个服务器端进行验证;服务器根据客户端的令牌,找到对应的凭证,返回给客户端,告诉客户端是否可以进行访问。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

namespace Example_SSO.Class
{
    /// <summary>
    /// 缓存管理
    /// 把令牌和主站凭证关系存入缓存
    /// </summary>
    public class CacheManager
    {
        /// <summary>
        /// 获取缓存中的table
        /// </summary>
        /// <returns></returns>
        public static DataTable GetCacheTable()
        {
            DataTable dt = null;
            if (HttpContext.Current.Cache["CERT"] != null)
            {
                dt =(DataTable) HttpContext.Current.Cache["CERT"];
            }
            return dt;
        }

        /// <summary>
        /// 初始化数据结构
        /// </summary>
        /// <remarks>
        /// ----------------------------------------------------
        /// | token(令牌) | info(用户凭证) | timeout(过期时间) |
        /// |--------------------------------------------------|
        /// </remarks>
        public static  void CacheInit()
        {
            if (HttpContext.Current.Cache["CERT"] == null)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("token", Type.GetType("System.String"));
                dt.Columns["token"].Unique = true;

                dt.Columns.Add("info", Type.GetType("System.Object"));
                dt.Columns["info"].DefaultValue = null;

                dt.Columns.Add("timeout", Type.GetType("System.DateTime"));
                dt.Columns["timeout"].DefaultValue=DateTime.Now.AddMinutes(double.Parse(System.Configuration.ConfigurationManager.AppSettings["timeout"]));

                DataColumn[] keys = new DataColumn[1];
                keys[0] = dt.Columns["token"];
                dt.PrimaryKey = keys;

                //cache 的过期时间为 令牌时间的2倍
                HttpContext.Current.Cache.Insert("CERT", dt,null, DateTime.MaxValue, TimeSpan.FromMinutes(double.Parse(System.Configuration.ConfigurationManager.AppSettings["timeout"]) * 2));

            }
        }


        /// <summary>
        /// 判断令牌是否存在
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool TokenIsExist(string token)
        {
            CacheInit();
            DataTable dt = (DataTable)HttpContext.Current.Cache["CERT"];
            if (dt.Select("token='" + token + "'").Length == 0)//令牌不存在
            {
                return false;
            }
            else //令牌存在
            {
                return true;
            }
        }



        /// <summary>
        /// 更新令牌时间
        /// </summary>
        /// <param name="token"></param>
        /// <param name="time"></param>
        public static void tokenTimeUpdate(string token, DateTime time)
        {
            CacheInit();
            DataTable dt = (DataTable)HttpContext.Current.Cache["CERT"];
            DataRow[] dr = dt.Select("token='"+token+"'");
            if (dr.Length > 0)
            {
                dr[0]["timeout"] = time;
            }
        }



        /// <summary>
        /// 添加令牌
        /// </summary>
        /// <param name="token"></param>
        /// <param name="info"></param>
        /// <param name="time"></param>
        public static void TokenInsert(string token, object info, DateTime timeout)
        {
            CacheInit();
            if (!TokenIsExist(token))//不存在
            {
                DataTable dt = (DataTable)HttpContext.Current.Cache["CERT"];
                DataRow dr = dt.NewRow();
                dr["Token"] = token;
                dr["info"] = info;
                dr["timeout"] = timeout;
                dt.Rows.Add(dr);
                HttpContext.Current.Cache["CERT"] = dt;
            }
            else
            {
                tokenTimeUpdate(token, timeout);
            }
        }
    }
}

服务器的服务:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using Example_SSO.Class;

namespace Example_SSO
{
    /// <summary>
    /// TokenService 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    // [System.Web.Script.Services.ScriptService]
    public class TokenService : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }



        /// <summary>
        /// 获取令牌的对应凭证
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [WebMethod]
        public object TokenGetGredence(string token)
        {
            object o = new object();
            DataTable dt = Example_SSO.Class.CacheManager.GetCacheTable();
            if (dt != null)
            {
                DataRow[] dr = dt.Select("token='" + token + "'");
                if (dr.Length > 0)
                {
                    o = dr[0]["info"];
                }
            }
            return o;
        }



        /// <summary>
        /// 清除令牌
        /// </summary>
        /// <param name="token"></param>
        [WebMethod]
        public static void TokenClear(string token)
        {
            DataTable dt = Example_SSO.Class.CacheManager.GetCacheTable();
            if (dt != null)
            {
                DataRow[] dr = dt.Select("token='"+token+"'");
                if (dr.Length > 0)
                {
                    dt.Rows.Remove(dr[0]);
                }
            }
        }
    }
}

 

2.客户端通过调用服务器的服务来验证令牌

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;


namespace SiteA.Class
{

    //授权页面基类
    public class AuthBase : System.Web.UI.Page
    {
        protected override void OnLoad(EventArgs e)
        {
           // base.OnLoad(e);
            if (Session["Token"] != null)
            {
                //凭证存在
                Response.Write("恭喜你,凭证存在");
            }
            else
            { 
                //令牌验证结果
                if (Request.QueryString["Token"] != null)
                {
                    if (Request.QueryString["Token"] != "$Token$")
                    {
                        //持有令牌
                        string tokenvalue = Request.QueryString["Token"].ToString();

                        //调用凭证验证服务,获取令牌对应的凭证
                        Example_SSO.TokenService tokenService = new Example_SSO.TokenService();
                        object o = tokenService.TokenGetGredence(tokenvalue);
                        if (o != null)
                        {
                            //令牌正确
                            Session["Token"] = o;
                            Response.Write("恭喜你,令牌存在");
                        }
                        else
                        {
                            Response.Write("令牌错误");
                        }
                    }
                    else
                    {
                        Response.Write("未持有令牌");
                    }
                }
                else
                {
                    Response.Redirect(this.getTokenURL());
                }
            }
            base.OnLoad(e);
        }



        /// <summary>
        /// 获取带令牌请求的url
        /// </summary>
        /// <returns></returns>
        public string getTokenURL()
        {
            string url = Request.Url.AbsoluteUri;
            Regex reg = new Regex(@"^.*\?.+=.+$");
            if (reg.IsMatch(url))
            {
                url += "$Token=$Token$";
            }
            else
            {
                url += "?Token=$Token$";
            }
            return "http://www.passport.com/gettoken.aspx?BackURL=" + Server.UrlEncode(url);
        }


        /// <summary>
        /// 去掉URL中的令牌
        /// 在当前URL中去掉令牌参数
        /// </summary>
        /// <returns></returns>
        private string replaceToken()
        {
            string url = Request.Url.AbsoluteUri;
            url = Regex.Replace(url, @"(\?|&)Token=.*", "", RegexOptions.IgnoreCase);
            return "http://www.passport.com/userlogin.aspx?BackURL=" + Server.UrlEncode(url);
        }
    }
}

 

posted @ 2015-07-15 14:56  成神之路~  阅读(295)  评论(0)    收藏  举报