• 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
        }
  • 相关阅读:
    opengl学习
    同步、异步、多线程与事件型综述
    Javascript异步编程的4种方法
    ASP.NET(C#) GridView (编辑、删除、更新、取消)
    浅析五大ASP.NET数据控件
    用 Eclipse 开发 Android 应用程序
    [C# 网络编程系列]专题十:实现简单的邮件收发器
    [C# 网络编程系列]专题九:实现类似QQ的即时通信程序
    [C# 网络编程系列]专题七:UDP编程补充——UDP广播程序的实现
    [C# 网络编程系列]专题六:UDP编程
  • 原文地址:https://www.cnblogs.com/linqing/p/5922433.html
Copyright © 2020-2023  润新知