Saas应用程序实现订阅级别

时间:2014-01-03 01:06:15

标签: c# asp.net-mvc asp.net-mvc-4 inversion-of-control

我处于SaaS应用程序的最后阶段(作为服务的软件)我有点束缚,我不知道要采取哪种方式。

我需要检查当前用户的订阅级别,看看他们是否可以使用他们想要覆盖的资源。

我目前处理这种方式(缺乏经验)的方法是,在需要进行此检查的每个操作中,我都会访问存储库并获取其订阅并根据SQL Server返回的数据做出决策。我个人认为这是最糟糕的做法,不喜欢它。

我考虑过制作一个可以进行检查的动作属性。虽然我相信这是一个更好的方法(减少代码重写和维护),但我认为必须有更好的方法。

我还考虑过制作助手并每次调用它并将结果存储在会话中但我没有太多的会话经验,并且已经听过并阅读过有关它和azure(一般的云平台)的恐怖故事

任何想法?

1 个答案:

答案 0 :(得分:1)

为此,我有AllowFor属性。它看起来像:

public class AllowFor : ActionFilterAttribute
{
    private UserType userTypes = UserType.NotAuthenticated;

    public AllowFor(UserType userTypes)
    {
        this.userTypes = userTypes;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!(filterContext.Controller is ApplicationController))
            throw new Exception("AllowFor attribute is acceptable only for ApplicationController");

        var controller = (ApplicationController)filterContext.Controller;

        if (!userTypes.HasFlag(controller.CurrentUserType))
            filterContext.Result = new ViewResult
            {
                ViewName = "AccessRestricted"
            };
        else
            base.OnActionExecuting(filterContext);
    }
}

ApplicationController只是继承自Contoller的类。

public abstract class Application : Controller
{
    public UserType CurrentUserType
    {
        get
        {
            return currentUser.UserType;
        }
    }

    // singleton for current user

    protected User __currentUser = null;
    protected User currentUser
    {
        get
        {
            if (__currentUser == null && HttpContext != null && HttpContext.User.Identity.IsAuthenticated)
            {
                // access to sql based on:
                // HttpContext.User.Identity.IsAuthenticated
                // HttpContext.User.Identity.Name
                // etc
            }
            return __currentUser;
        }
    }

    // singleton for EF context

    private MyAppContext __context = null;
    protected MyAppContext context
    {
        get
        {
            if (__context == null)
            {
                __context = new MyAppContext();
            }
            return __context;
        }
    }
}

你实际上并不需要它,但我发现它非常有用。只需从ApplicationContoller继承您的控制器,您就可以使用单例模式检索上下文和其他对象。

属性的使用非常简单,只需使用属性标记您的操作:

[Authorize, AllowFor(UserType.Company)]
public ActionResult Index()
{
    // ...
}

您可以使AllowFor属性更有用,并将其应用于类(例如控制器)而不是操作:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
                AllowMultiple = false, Inherited = true)]
public class AllowFor : ActionFilterAttribute { ... }