【问题标题】:How should the restriction be done when the subscription period expires?订阅期满后如何限制?
【发布时间】:2020-10-01 06:42:26
【问题描述】:

在一个使用 .Net Core 3.1 开发的 Rest Api SaaS 项目中。

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

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

方法一)在生成JWT时检查订阅状态,如果订阅期已过则不生成JWT:

如果我使用这种方法;

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

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

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

如果我使用这种方法;

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

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

这是我的想法......

或其他解决方案...

我们应该如何限制订阅到期的用户,我们应该如何处理?

非常感谢您的信息分享。

【问题讨论】:

  • JSON Web 令牌用于身份验证。用户的订阅是否过期是授权的问题,应该单独处理。

标签: c# asp.net-core-webapi payment saas


【解决方案1】:

我使用方法 2 解决了我上面提出的问题。

我想解释一下我是如何做到的,因为我认为这可能会对将来调查这个问题的人有所帮助。

我在方法2中说过,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”。

希望它有利于您的业务...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2021-09-11
    • 1970-01-01
    • 2017-04-12
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多