订阅期满应该怎么限制?

How should the restriction be done when the subscription period expires?

Rest Api SaaS 项目中使用 .Net Core 3.1.

开发

当用户的订阅到期(需要付费)时,采用什么样的方式比较好

我想到了2种方法,但我认为这两种方法都会有一些问题。

方法1)生成JWT时检查订阅状态,订阅期过后不生成JWT:

如果我用这个方法;

优点:由于不会给订阅到期的用户一个token, 他们将无法访问其他端点。 我认为这将非常安全,无需进行任何其他编码工作。

缺点:当我需要将用户重定向到支付页面时, 由于没有令牌,我将不得不为支付端点做一些特殊的工作。(例如:密码重置方法) 我会用查询字符串得到它,我想我可以为这个方法创建一个特殊的标记。 但我认为可能存在安全漏洞,因为我无法使用标准授权方法保护此进程?

方法2)即使订阅过期,也会生成jwt,但会限制会员:

如果我用这个方法;

优点:我可以毫无问题地使用我的标准授权方法 当我需要将用户定向到支付端点或另一个端点时。 我将与 jwt 一起使用,安全漏洞将大大减少。

缺点:我需要为订阅期已过的用户确定无法在应用程序上访问的端点 我将需要在中间件中编写一个工作服务,使它们无法访问。 (喜欢权限方法) 这都将进行额外的编码工作,并且每个端点都需要额外的工作。

这些是我的想法....

或其他解决方案...

我们应该如何限制订阅到期的用户以及我们应该如何操作?

非常感谢您的信息分享

我用方法二解决了我上面问的问题

我想解释一下我是怎么做到的,因为我认为这可能会对以后研究这个问题的人有所帮助。

我在方法二中说了,jwt已经生成但是成员限制。


首先,在生成令牌时,我设置声明他们是否有订阅。

....
new Claim(JwtClaimIdentifier.HasSubscription, hasSubscription)

这里就不详细解释了。标准声明。


订阅控制

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class SubscriptionRequiredAttribute : TypeFilterAttribute
{
    public SubscriptionRequiredAttribute()
        : base(typeof(SubscriptionFilter)) { }
}

--

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class AllowWithoutSubscriptionAttribute : Attribute
{
    public AllowWithoutSubscriptionAttribute() { }
}

--

public class SubscriptionFilter : IAuthorizationFilter
{
    private bool AllowWithoutSubscription(AuthorizationFilterContext context)
    {
        var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        bool allowWithoutSubscriptionForMethod = controllerActionDescriptor.MethodInfo.CustomAttributes.Any(x => x.AttributeType == typeof(AllowWithoutSubscriptionAttribute));
        if (allowWithoutSubscriptionForMethod)
            return true;

        bool allowWithoutSubscriptionForController = controllerActionDescriptor.ControllerTypeInfo.CustomAttributes.Any(x => x.AttributeType == typeof(AllowWithoutSubscriptionAttribute));
        if (allowWithoutSubscriptionForController)
            return true;

        return false;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (AllowWithoutSubscription(context))
            return;

        var hasSubscription = context.HttpContext.User.Claims.First(x => x.Type == JwtClaimIdentifier.HasSubscription).Value.ToLower() == "true";
        if (!hasSubscription)
            context.Result = new BadRequestObjectResult(**ErrorCode**);
    }
}

我添加了一个覆盖订阅控制的属性。

例如;要在控制器或方法中使用它,我需要在检查基础上的订阅时覆盖它。

使用控制器

[SubscriptionRequired]
public class FooController
{
public async Task<IActionResult> FooMethodOne(){...}

public async Task<IActionResult> FooMethodTwo(){...}

[AllowWithoutSubscription]
public async Task<IActionResult> FooMethodThree(){...}
}

虽然上面的 FooMethodOne 和 FooMethodTwo 需要订阅,但 FooMethodThree 无需订阅即可工作。

同样,所有控件都称为“AllowWithoutSubscription”。 它也可以在方法中称为“SubscriptionRequired”。

希望它对您的业务有益...