【问题标题】:Is it possible to enable session state for authenticated users only in ASP.NET MVC?是否可以仅在 ASP.NET MVC 中为经过身份验证的用户启用会话状态?
【发布时间】:2012-06-02 15:29:21
【问题描述】:

MVC3 添加了一个使用[SessionState(SessionStateBehavior.Disabled)] 属性制作无会话控制器的好机会。这很好但不够灵活,因为您不能为每个控制器方法设置会话状态,也不能按条件启用它。

是否可以仅为经过身份验证的用户启用会话状态或通过其他一些自定义条件启用会话状态? IE。 PHP 有一个很棒的特性。 if (!isset($_SESSION)) session_start(); 能找到这样的东西就好了

【问题讨论】:

    标签: asp.net-mvc-3 session session-state


    【解决方案1】:

    您可以覆盖默认控制器工厂,更具体地说是 GetControllerSessionBehavior 方法:

    public class MyControllerFactory : DefaultControllerFactory
    {
        protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                return SessionStateBehavior.Default;
            }
    
            if (requestContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // enable session if there's an authenticated user
                return SessionStateBehavior.Required;
            }
    
            return SessionStateBehavior.Disabled;
        }
    }
    

    并在Application_Start 中将默认控制器工厂替换为自定义控制器:

    ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
    

    【讨论】:

    • 太棒了!谢谢!我还将扩展它以允许对每个控制器方法使用属性(以防您需要为匿名用户使用 TempData)。不知道能不能从RequestContext获取执行方法名
    • 是的,我做到了。如果有人对禁用每个控制器方法的会话状态感兴趣,请在这里问我,我会分享我的解决方案!
    • @Cheburek .. 你能和我分享你的解决方案吗?
    • @alok_dida 请见下文。
    【解决方案2】:

    如何按控制器方法禁用会话状态。 即使对于这样的流程,它也能正常工作:

    1. 启用会话的请求方法
    2. 禁用会话的请求方法
    3. 启用会话的请求方法 - 保留值(我不明白为什么,但确实如此)

        /// <summary>
        /// Enable session if there's an authenticated user or method in controller is marked with <see cref="SessionAttribute" /> or controller class is marked within <see cref="SessionAttribute" /> or <see cref="SessionStateAttribute" />
        /// </summary>
        public class AuthSessionControllerFactory : DefaultControllerFactory
        {
      
          protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
          {
            if ( controllerType == null ) return SessionStateBehavior.Default;
      
            return requestContext.HttpContext.User.Identity.IsAuthenticated
              ? SessionStateBehavior.Required
              : GetDefaultSessionBehavior( requestContext, controllerType );
          }
      
       private static readonly ConcurrentDictionary<string, SessionStateBehavior> _sessionStateCache = new ConcurrentDictionary<string, SessionStateBehavior>();
       protected SessionStateBehavior GetDefaultSessionBehavior(RequestContext requestContext, Type controllerType)
       {
        if ( !requestContext.RouteData.Values.Keys.Contains( "action" ) ) return SessionStateBehavior.Required;
        var act = requestContext.RouteData.Values["action"].ToString();
      
        return _sessionStateCache.GetOrAdd( controllerType + act,
          (type => {
            var typeCopy = controllerType;
      
            //get current action
            var methods = typeCopy.GetMethods().Where( m => m.Name == act ).ToArray();
            foreach (var method in methods) {
      
              //look for SessionAttribute on the method
              var attr = Attribute.GetCustomAttribute( method, typeof( SessionAttribute ), false );
              if ( attr != null ) return (( SessionAttribute )attr).Behavior;
      
      
              //support default SessionState behavior
              var controllerattr = typeCopy.GetCustomAttributes( typeof( SessionStateAttribute ), true )
                .OfType<SessionStateAttribute>().FirstOrDefault();
              if ( controllerattr == null ) 
              {
                var controllerattrCustom = typeCopy.GetCustomAttributes( typeof( SessionAttribute ), true )
                  .OfType<SessionAttribute>().FirstOrDefault();
                if ( controllerattrCustom != null ) return controllerattrCustom.Behavior;
              } else
                return controllerattr.Behavior;
            }
            return SessionStateBehavior.Disabled;
      
          }) );
      }
      

      }

    在 Global.asax 的Application_Start() 方法中注册

    ControllerBuilder.Current.SetControllerFactory( new AuthUserSessionControllerFactory() );  
    

    这是一个 SessionAttribute 类 - 它看起来像 MS 的 SessionStateAttribute - 唯一的区别是方法允许使用这个类

    [AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true )]
      public sealed class SessionAttribute : Attribute
      {
    
        public SessionAttribute(SessionStateBehavior behavior)
        {
          Behavior = behavior;
        }
    
        public SessionStateBehavior Behavior { get; private set; }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多