MVC5 一套Action的登录控制流程

流程:

用拦截器控制每一个页面请求和ajax请求,根据请求体的cookie里面是否有token判断是否登录,还必须判断该token在redis里面的缓存是否存在

组成部分:

拦截器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Rongzi.RZR.Huoke.Infrastructure.Util;
using Rongzi.RZR.Huoke.Entity;
using Rongzi.RZR.Huoke.Entity.Constants;
using Rongzi.RZR.Huoke.Infrastructure.Model;
using Rongzi.RZR.Huoke.Entity.Models;

namespace Rongzi.RZR.Huoke.Infrastructure.Filter
{
   public  class ApiAuthFilterAttribute:System.Web.Mvc.ActionFilterAttribute
    {
        public bool isDoCheck { get; set; }
        public ApiAuthFilterAttribute()
        {
            isDoCheck = true;
        }
        public ApiAuthFilterAttribute(bool isCheck = true)
        {
            isDoCheck = isCheck;
        }

        public override void OnActionExecuting(ActionExecutingContext actionContext)
        {
            if (isDoCheck)
            {

                if (actionContext == null || actionContext.HttpContext.Request == null || actionContext.HttpContext.Request.RawUrl == null) { return; }
                //string token = actionContext.HttpContext.Request.Headers["token"] ?? actionContext.HttpContext.Request.Cookies["token"].Value;
 
                string token = actionContext.HttpContext.Request.Cookies["token"]?.Value;
                if (string.IsNullOrEmpty(token))
                {
                    if (actionContext.HttpContext.Request.IsAjaxRequest())
                    {
                        actionContext.Result = GetAuthJsonResult();
                    }
                    else
                    {
                        actionContext.HttpContext.Response.Redirect("~/Account/Login");
                    }
                    return;
                }
                RedisOpearteResult redRes = TokenManager<OrganizationUser>.RefreshUserToken(token);
                if (!redRes.isok)
                {
                    if (actionContext.HttpContext.Request.IsAjaxRequest())
                    {
                        actionContext.Result = GetAuthJsonResult();
                    }
                    else
                    {
                        actionContext.HttpContext.Response.Redirect("~/Account/Login");
                    }
                    base.OnActionExecuting(actionContext);
                    return;
                }
            }
            base.OnActionExecuting(actionContext);
        }


        public static JsonResult GetAuthJsonResult()
        {
            var errResponse = new ResponseContext<string>();
            errResponse.Head = new ResponseHead(-1, ErrCode.AuthError, "用户还未登录");
            return new JsonResult
            {
                Data = errResponse,
                ContentEncoding = System.Text.Encoding.UTF8,
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }

        public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
        {
            base.OnActionExecuted(actionExecutedContext);
        }
    }
}
View Code

控制登录管理:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Rongzi.RZR.Huoke.Entity.Models;
using Rongzi.RZR.Huoke.Infrastructure.Util;
using Rongzi.RZR.Huoke.Infrastructure.Model;

namespace Rongzi.RZR.Huoke.Infrastructure
{
    public class FormsAuth
    {
        ///// <summary>
        ///// 生成Userdata
        ///// </summary>
        ///// <param name="user">用户model</param>
        ///// <returns></returns>
        //private static string GenerateUserData(long userId, string userName, string userAccount, string imageUrl)
        //{
        //    return string.Join("|", userId, userName, userAccount, imageUrl);
        //}

        ///// <summary>
        ///// 登录系统
        ///// </summary>
        ///// <param name="user">用户model</param>
        ///// <param name="isRemember"是否记住></param>
        ///// <param name="days">超时时间</param>
        //public static void SignIn(long userId, string userName, string userAccount, string imageUrl, bool isRemember, int days)
        //{
        //    var userData = GenerateUserData(userId, userName, userAccount, imageUrl);
        //    var enyUserData = DEncrypt.Encrypt(userData);
        //    var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddDays(days), isRemember, enyUserData);
        //    var enyTicket = FormsAuthentication.Encrypt(ticket);

        //    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, enyTicket);

        //    HttpContext.Current.Response.Cookies.Add(authCookie);
        //}

        /// <summary>
        /// 登录系统
        /// </summary>
        /// <param name="user"></param>
        public static void SignIn(OrganizationUser user)
        {
            RedisOpearteResult result = TokenManager<OrganizationUser>.getToken(user);
            var authCookie = new HttpCookie("token", result.token);
            HttpContext.Current.Response.SetCookie(authCookie);
           
        }

        /// <summary>
        /// 退出系统
        /// </summary>
        /// <param name="token"></param>
        public static void SignOff()
        {
            var cookie = HttpContext.Current.Request.Cookies["token"];
            if (cookie != null)
            {
                string token = cookie.Value;
                TokenManager<OrganizationUser>.LoginOff(token);
                HttpContext.Current.Response.Cookies["token"].Expires = DateTime.Now.AddDays(-1);
            }
        }

        public static OrganizationUser GetUserInfo()
        {
            var cookie = HttpContext.Current.Request.Cookies["token"];
            if (cookie != null)
            {
                string token = cookie.Value;
                return TokenManager<OrganizationUser>.getUserByToken(token);
            }
            return null;
        }
    }
}
View Code

TokenManager管理:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Rongzi.Cache.Redis;
using System.Configuration;
using Rongzi.RZR.Huoke.Infrastructure.Model;

namespace Rongzi.RZR.Huoke.Infrastructure.Util
{
    public class TokenManager<TUser>
    {
        /// <summary>
        /// 设置对象过期时间
        /// </summary>
        private static readonly int interval = Convert.ToInt32(ConfigurationManager.AppSettings["Redis_UserExpire"]);
        private static readonly string prefix = "OrganizationUser:";

        /// <summary>
        /// 存储对象val,获取对应的token
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static RedisOpearteResult getToken(TUser val)
        {
            string tokenID = Guid.NewGuid().ToString();
            RedisOpearteResult result = new RedisOpearteResult
            {
                isok = RedisCache.Add(prefix + tokenID, val, interval),
                token = tokenID,
                result = JsonConvert.SerializeObject(val)
            };
            return result;
        }

        /// <summary>
        /// 根据tokenID更新用户对象
        /// </summary>
        /// <param name="tokenID"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static RedisOpearteResult RefreshLoginTokenData(String tokenID, TUser val)
        {
            RedisOpearteResult result = new RedisOpearteResult
            {
                isok = RedisCache.Add(prefix + tokenID, val, interval),
                token = tokenID,
                result = JsonConvert.SerializeObject(val)
            };
            return result;
        }

        /// <summary>
        /// 刷新用户token
        /// </summary>
        /// <param name="tokenID"></param>
        public static RedisOpearteResult RefreshUserToken(string tokenID)
        {
            var obj = RedisCache.Get<TUser>(prefix + tokenID);
            var isExist = obj != null;
            RedisOpearteResult result = new RedisOpearteResult
            {
                isok = isExist,
                token = tokenID,
                result = "Token过期"
            };
            if (isExist)
            {
                result.result = "成功延迟";
                RedisCache.SetExpire(prefix + tokenID, new TimeSpan(0, interval, 0));
            }
            return result;
        }

        /// <summary>
        /// 退出
        /// </summary>
        /// <param name="tokenID"></param>
        /// <returns></returns>
        public static RedisOpearteResult LoginOff(string tokenID)
        {
            var obj = RedisCache.Get<TUser>(prefix + tokenID);
            var isExist = obj != null;
            RedisOpearteResult result = new RedisOpearteResult
            {
                isok = isExist,
                token = tokenID,
                result = "Token过期"
            };
            if (isExist)
            {
                result.result = "退出成功";
                RedisCache.Remove(prefix + tokenID);
            }
            return result;
        }

        /// <summary>
        /// 通过token 获取用户信息
        /// </summary>
        /// <param name="token">tokenID</param>
        /// <returns></returns>
        public static TUser getUserByToken(string tokenID)
        {
            if (!string.IsNullOrEmpty(tokenID))
            {
                return RedisCache.Get<TUser>(prefix + tokenID);
            }
            return default(TUser);
        }
    }
}
View Code

其他:

 public class RedisOpearteResult
    {
        public string token { get; set; }
        public bool isok { get; set; }
        public int code { get; set; }
        public object data { get; set; }
        public string result { get; set; }

    }
View Code

其实整个流程不难,下面说说坑:

Cookie的修改

登录时,不能使用

 HttpContext.Current.Response.Cookies.Add(authCookie);

这个是不断的添加cookie,有相同路径的,就添加不同路径的

应该使用:

 HttpContext.Current.Response.SetCookie(authCookie);

这个才是唯一性的,有就修改,没有就添加

Cookie的删除:

HttpContext.Current.Response.Cookies.Remove("token");

这个是旧的使用方式,发现怎么也没有用,浏览器中还是有这个cookie,后来查询资料,这个就对服务器中的cookies进行删除,但是并不对浏览器中的cookie进行操作。

应该使用过期时间:

 HttpContext.Current.Response.Cookies["token"].Expires = DateTime.Now.AddDays(-1);

还有一点,获取cookie的信息的时候使用Request的,不要使用Response的,发现对象存在,但是里面的值是空字符串

var cookie = HttpContext.Current.Request.Cookies["token"];

上面3个就是我踩的坑,以后注意!

posted @ 2017-08-04 19:37  hongdada  阅读(423)  评论(0编辑  收藏  举报