老司机翻车记--为什么Session会取不到值

版权声明:本文为starfd原创文章,转载请标明出处。 https://blog.csdn.net/starfd/article/details/82255291

作为一个资深的老司机,用MVC5的WebApi做了个小应用,项目前后端分离,然后需要保持用户登录信息,所以很简单的通过在Global.asax文件中增加相应代码来使WebApi支持Session

        public override void Init()
        {
            this.PostAuthorizeRequest += (sender, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
            base.Init();
        }

然后用于存放当前用户信息的POCO类声明大致如下

    public class AuthInfo
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

定义用于校验是否登录的Attribute

    public class ApiAuthorizeAttribute : AuthorizeAttribute
    {

        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
#if DEBUG
            return true;
#else
            return HttpContext.Current.Session[Consts.AuthSessionKey] as AuthInfo != null;
#endif
            //return base.IsAuthorized(actionContext);
        }
    }

最后定义一个所有需要登录验证的基类

    [ApiAuthorize]
    public abstract class ApiAuthBaseController : ApiController
    {
        /// <summary>
        /// 当前登录用户信息
        /// </summary>
        public AuthInfo AuthInfo
        {
            get
            {
#if DEBUG
                return new AuthInfo
                {
                    Id = "001",
                    Name = "张三",
                };
#else
                return HttpContext.Current.Session[Consts.AuthSessionKey] as AuthInfo;
#endif
            }
        }
    }

最终项目测试一切正常,但因为测试过程中经常需要重新发布,前端对于每次重发后就要重新登录感到不爽,为了和睦同事关系,咋必须做点事来解决这问题是不,所以问题就来了!

因为默认Session采用的Mode是InProc,只要任何导致IIS回收应用的情况产生,都会使当前应用的Session全被清除,所以简单的将Mode改为StateServer即可。

信心满满的改完配置,测试登录接口发现没啥问题,妥妥的告知前端此时已经搞定,结果半分钟不到,前端立马打脸过来,为啥登录完了,访问其它接口都返回401未授权!!!

事实告诉我们,再怎样的老司机,改完代码或者配置还是需要做些相应功能的完整测试,本地开启调试模式,Debug发现HttpContext.Current.Session在登录后是有值的,但到ApiAuthorizeAttribute时该值就取不出来了,也就导致每次IsAuthorized判断返回的都是false,这是为啥?

将Mode改回InProc,测试时的确又可以取到Session,百思不得其解,百度、bing了一番也没找到任何类似的问题,难道老司机就要翻车了?

当代码问题悬而未解时,历史经验告诉我们,反复钻牛角是没用的,去做些其它事情(比如喝喝水,上上厕所)转变一下状态,解决问题的答案可能就会突然出现在脑海里,果然上个厕所回来脑中突然灵光一闪,StateServer已经脱离了当前应用,那么复杂实体就需要序列化之后才能写入StateServer中,而目前AuthInfo并没有声明SerializableAttribute,实际动手为AuthInfo加上[Serializable]声明后,再测试果然问题成功解决了!

其实在写入Session时,框架如果返回了序列化失败异常的话,问题原因早就被发现了,但不知道为啥MVC框架没有这么做……

猜你喜欢

转载自blog.csdn.net/starfd/article/details/82255291
今日推荐