MVC SSO登陆 的麻烦事~

前段时间用MVC + Redis 做session搞了个简单的单点登录Web站。真是日了狗的问题多。

今天正好睡不着,做个备忘笔记>_<

实现方法很简单,无非就是从重载个Controller或 做一个ActionFilterAttribute就可以达到目的。

下面贴一个Controller的代码实现,ActionFilterAttribute实现方式类似

这里我为了图方便用了servicestack.redis 虽然最新的免费版本 有很大的性能限制(真坑爹)。

两个Controller 类,Base用于在Action执行前填充的Account信息,一个要求必须登陆,否则调到SSO

PS:可做小修改,例如带Token时二次重定向刷新页面或是将Token存入Cache。

    
/// <summary>
/// 为所有Action填充Account用户信息
/// </summary>

  public class BaseAccountController : Controller { protected RedisHelper.RedisHelper redisHelper { get; private set; } protected readonly static String TokenKeyCookie = "QTMAccountTokenCookie"; public BaseAccountController() { redisHelper = new RedisHelper.RedisHelper(); } ~BaseAccountController() { if (redisHelper != null) { redisHelper.Dispose(); } } protected override void OnActionExecuting(ActionExecutingContext filterContext) { var cookie = filterContext.HttpContext.Request.Cookies[TokenKeyCookie]; String token = filterContext.HttpContext.Request.QueryString["Token"]; if (cookie != null) { token = cookie.Value; var accountIndex = redisHelper.Get<AccountIndex>(token); ViewBag.CurrentAccount = accountIndex; } else if (!String.IsNullOrWhiteSpace(token)) { var accountIndex = CreateTokenCookie(token); ViewBag.CurrentAccount = accountIndex; } } /// <summary> /// 创建Token令牌的本地Cookie /// </summary> /// <param name="Token">Token令牌</param> /// <returns></returns> protected AccountIndex CreateTokenCookie(string Token) { var accountIndex = redisHelper.Get<AccountIndex>(Token); //判断是否 为有效的Token令牌 if (accountIndex == null) { return null; } //生产Token令牌的Cookie var token_cookie = new HttpCookie(TokenKeyCookie, Token) { HttpOnly = true, Secure = FormsAuthentication.RequireSSL, Path = "/", Expires = DateTime.Now.AddYears(10) }; HttpContext.Response.Cookies.Add(token_cookie); return accountIndex; }

    /// <summary>
    /// 控制器的 所有Action必须 持有 有效的 Account Token令牌。
    /// </summary>
    public class AccountAuthenController : BaseAccountController
    {

        public AccountAuthenController()
            : base()
        {
        }

        ~AccountAuthenController()
        {
            if (redisHelper != null)
            {
                redisHelper.Dispose();
            }
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            String token = filterContext.HttpContext.Request.QueryString["Token"];
            var cookie = filterContext.HttpContext.Request.Cookies[TokenKeyCookie];

            if (cookie == null)
            {
                if (!String.IsNullOrWhiteSpace(token))
                {
                    //当有返回新的Token令牌时,创建一个新的Token本地Cookie
                    var accountIndex = CreateTokenCookie(token);

                    if (accountIndex == null)
                    {
                        filterContext.HttpContext.Response.Redirect(String.Format(ActionUri.Login, filterContext.HttpContext.Request.Url.AbsoluteUri));
                    }
                }
                else
                {
                    filterContext.HttpContext.Response.Redirect(String.Format(ActionUri.Login, filterContext.HttpContext.Request.Url.AbsoluteUri));
                }
            }
            else
            {
                token = cookie.Value;
                var accountIndex = redisHelper.Get<AccountIndex>(token);

                if (accountIndex == null)
                {   //无效的Token Cookie
                    filterContext.HttpContext.Response.Cookies[TokenKeyCookie].Expires = DateTime.Now.AddYears(-1);
                    filterContext.HttpContext.Response.Redirect(String.Format(ActionUri.Login, filterContext.HttpContext.Request.Url.AbsoluteUri));
                }
            }

            base.OnActionExecuting(filterContext);
        }

        #region Private Method



        #endregion
    }
原文地址:https://www.cnblogs.com/linqing/p/5922433.html