.NET 的网站邀请系统/测试版锁定?

发布于 2024-10-21 16:43:29 字数 427 浏览 4 评论 0原文

是否有任何适用于 .NET 的开源解决方案(首选 C# / MVC)允许在私人滚动 Beta 场景中使用简单的锁定和邀请系统?

除非用户登录(可能使用全局操作过滤器),否则用户几乎会被重定向到启动页面...

以下是其他语言的几个类似的解决方案:

https://github.com/ejdraper/exclusivity (Ruby)

https://github.com/pragmaticbadger/django-privatebeta (Python)

Are there any open source solutions for .NET (prefer C# / MVC) that allow for simple lockdown and invitation system useful in a private rolling Beta scenario?

Pretty much where the user would be redirected to a splash page unless they are logged in (perhaps using Global Action Filters)...

Here are a couple similar solutions in other languages:

https://github.com/ejdraper/exclusivity (Ruby)

https://github.com/pragmaticbadger/django-privatebeta (Python)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

话少情深 2024-10-28 16:43:29

我为 ASP.NET MVC 编写了一个由配置文件驱动的小型“访问控制”过滤器。我可以在 web.config 中切换一个标志,该标志会将所有未注册的用户移动到特定页面,除非他们特别请求登录或注销操作。您可以相应地调整您的实现,而不会遇到太多麻烦。

过滤器属性

public class AccessControlAttribute : AuthorizeAttribute
{
    public bool AccessControlEnabled {
        get { return AccessControlSection.Settings != null; }
    }

    public bool LockoutEnabled {
        get { return AccessControlEnabled && AccessControlSection.Settings.ForceLockout != null && AccessControlSection.Settings.ForceLockout.Enabled; }
    }

    public AccessControlAttribute() {
        if (LockoutEnabled) {
            Roles = AccessControlSection.Settings.ForceLockout.AllowRoles;
            Users = AccessControlSection.Settings.ForceLockout.AllowUsers;
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        if (filterContext.IsChildAction || ApproveLockoutAction(filterContext))
            return;

        if (LockoutEnabled && !string.IsNullOrEmpty(AccessControlSection.Settings.ForceLockout.DefaultPage)) {
            filterContext.HttpContext.Response.Redirect(AccessControlSection.Settings.ForceLockout.DefaultPage, false);
            return;
        }

        base.HandleUnauthorizedRequest(filterContext);
    }

    private static bool ApproveLockoutAction(AuthorizationContext filterContext) {
        var forceLockout = AccessControlSection.Settings.ForceLockout;
        if (forceLockout == null || !forceLockout.Enabled)
            return true;

        if (string.IsNullOrEmpty(forceLockout.LogOnUrl) || string.IsNullOrEmpty(forceLockout.LogOffUrl))
            return false;

        if (filterContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath.Equals(forceLockout.LogOnUrl, StringComparison.OrdinalIgnoreCase)
            || filterContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath.Equals(forceLockout.LogOffUrl, StringComparison.OrdinalIgnoreCase)) {
            return true;
        }

        return false;
    }
}

配置处理程序

public class AccessControlSection : ConfigurationSection
{
    public const string SectionName = "accessControl";
    public const string ForceLockoutKeyName = "forceLockout";

    private static AccessControlSection _settings;
    public static AccessControlSection Settings {
        get {
            if (_settings == null) {
                object section = ConfigurationManager.GetSection(SectionName);
                if (section != null)
                    _settings = section as AccessControlSection;
            }
            return _settings;
        }
    }

    [ConfigurationProperty(ForceLockoutKeyName)]
    public ForceLockoutElement ForceLockout {
        get { return (ForceLockoutElement)this[ForceLockoutKeyName]; }
        set { this[ForceLockoutKeyName] = value; }
    }
}

public class ForceLockoutElement : ConfigurationElement
{
    public const string AllowRolesKeyName = "allowRoles";
    public const string AllowUsersKeyName = "allowUsers";
    public const string DefaultPageKeyName = "defaultPage";
    public const string EnabledKeyName = "enabled";
    public const string LogOnUrlKeyName = "logOnUrl";
    public const string LogOffUrlKeyName = "logOffUrl";

    [ConfigurationProperty(AllowRolesKeyName, DefaultValue = "Admin")]
    public string AllowRoles {
        get { return (string)this[AllowRolesKeyName]; }
        set { this[AllowRolesKeyName] = value; }
    }

    [ConfigurationProperty(AllowUsersKeyName)]
    public string AllowUsers {
        get { return (string)this[AllowUsersKeyName]; }
        set { this[AllowUsersKeyName] = value; }
    }

    [ConfigurationProperty(DefaultPageKeyName, DefaultValue = "~/offline.htm")]
    public string DefaultPage {
        get { return (string)this[DefaultPageKeyName]; }
        set { this[DefaultPageKeyName] = value; }
    }

    [ConfigurationProperty(LogOnUrlKeyName, DefaultValue = "~/auth/logon")]
    public string LogOnUrl {
        get { return (string)this[LogOnUrlKeyName]; }
        set { this[LogOnUrlKeyName] = value; }
    }

    [ConfigurationProperty(LogOffUrlKeyName, DefaultValue = "~/auth/logoff")]
    public string LogOffUrl {
        get { return (string)this[LogOffUrlKeyName]; }
        set { this[LogOffUrlKeyName] = value; }
    }

    [ConfigurationProperty(EnabledKeyName, DefaultValue = true)]
    public bool Enabled {
        get { return (bool)this[EnabledKeyName]; }
        set { this[EnabledKeyName] = value; }
    }

    public string[] AllowedUsersArray {
        get {
            if (string.IsNullOrEmpty(AllowUsers))
                return null;

            return AllowUsers.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
        }
    }

    public string[] AllowRolesArray {
        get {
            if (string.IsNullOrEmpty(AllowRoles))
                return null;

            return AllowRoles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        }
    }
}

Web.config 示例

<configuration>
    <configSections>
        <section name="accessControl" type="MyWebsite.Config.AccessControlSection, MyWebsite" />
    </configSections>

    <accessControl>
        <forceLockout enabled="true" defaultPage="~/inviteonly.htm" 
            logOnUrl="~/logon" 
            logOffUrl="~/logoff" 
            allowRoles="Members" />
    </accessControl>

</configuration>

通过上述配置,任何未登录或不是“Members”角色成员的用户' 将被重定向到 '~/inviteonly.htm'。您可以通过用逗号分隔“allowRoles”和“allowUsers”属性中的值来指定多个允许的角色和/或用户。

AccessControlAttribute 必须注册为全局过滤器,或者放置在 BaseController 类定义中才能使一切正常工作。

I wrote a small 'access control' filter for ASP.NET MVC that is config file driven. I can switch a flag in my web.config which will move all unregistered users to a specific page unless they specifically request the login or logout actions. You could adapt your implementation accordingly without much trouble.

Filter Attribute

public class AccessControlAttribute : AuthorizeAttribute
{
    public bool AccessControlEnabled {
        get { return AccessControlSection.Settings != null; }
    }

    public bool LockoutEnabled {
        get { return AccessControlEnabled && AccessControlSection.Settings.ForceLockout != null && AccessControlSection.Settings.ForceLockout.Enabled; }
    }

    public AccessControlAttribute() {
        if (LockoutEnabled) {
            Roles = AccessControlSection.Settings.ForceLockout.AllowRoles;
            Users = AccessControlSection.Settings.ForceLockout.AllowUsers;
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        if (filterContext.IsChildAction || ApproveLockoutAction(filterContext))
            return;

        if (LockoutEnabled && !string.IsNullOrEmpty(AccessControlSection.Settings.ForceLockout.DefaultPage)) {
            filterContext.HttpContext.Response.Redirect(AccessControlSection.Settings.ForceLockout.DefaultPage, false);
            return;
        }

        base.HandleUnauthorizedRequest(filterContext);
    }

    private static bool ApproveLockoutAction(AuthorizationContext filterContext) {
        var forceLockout = AccessControlSection.Settings.ForceLockout;
        if (forceLockout == null || !forceLockout.Enabled)
            return true;

        if (string.IsNullOrEmpty(forceLockout.LogOnUrl) || string.IsNullOrEmpty(forceLockout.LogOffUrl))
            return false;

        if (filterContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath.Equals(forceLockout.LogOnUrl, StringComparison.OrdinalIgnoreCase)
            || filterContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath.Equals(forceLockout.LogOffUrl, StringComparison.OrdinalIgnoreCase)) {
            return true;
        }

        return false;
    }
}

Config Handler

public class AccessControlSection : ConfigurationSection
{
    public const string SectionName = "accessControl";
    public const string ForceLockoutKeyName = "forceLockout";

    private static AccessControlSection _settings;
    public static AccessControlSection Settings {
        get {
            if (_settings == null) {
                object section = ConfigurationManager.GetSection(SectionName);
                if (section != null)
                    _settings = section as AccessControlSection;
            }
            return _settings;
        }
    }

    [ConfigurationProperty(ForceLockoutKeyName)]
    public ForceLockoutElement ForceLockout {
        get { return (ForceLockoutElement)this[ForceLockoutKeyName]; }
        set { this[ForceLockoutKeyName] = value; }
    }
}

public class ForceLockoutElement : ConfigurationElement
{
    public const string AllowRolesKeyName = "allowRoles";
    public const string AllowUsersKeyName = "allowUsers";
    public const string DefaultPageKeyName = "defaultPage";
    public const string EnabledKeyName = "enabled";
    public const string LogOnUrlKeyName = "logOnUrl";
    public const string LogOffUrlKeyName = "logOffUrl";

    [ConfigurationProperty(AllowRolesKeyName, DefaultValue = "Admin")]
    public string AllowRoles {
        get { return (string)this[AllowRolesKeyName]; }
        set { this[AllowRolesKeyName] = value; }
    }

    [ConfigurationProperty(AllowUsersKeyName)]
    public string AllowUsers {
        get { return (string)this[AllowUsersKeyName]; }
        set { this[AllowUsersKeyName] = value; }
    }

    [ConfigurationProperty(DefaultPageKeyName, DefaultValue = "~/offline.htm")]
    public string DefaultPage {
        get { return (string)this[DefaultPageKeyName]; }
        set { this[DefaultPageKeyName] = value; }
    }

    [ConfigurationProperty(LogOnUrlKeyName, DefaultValue = "~/auth/logon")]
    public string LogOnUrl {
        get { return (string)this[LogOnUrlKeyName]; }
        set { this[LogOnUrlKeyName] = value; }
    }

    [ConfigurationProperty(LogOffUrlKeyName, DefaultValue = "~/auth/logoff")]
    public string LogOffUrl {
        get { return (string)this[LogOffUrlKeyName]; }
        set { this[LogOffUrlKeyName] = value; }
    }

    [ConfigurationProperty(EnabledKeyName, DefaultValue = true)]
    public bool Enabled {
        get { return (bool)this[EnabledKeyName]; }
        set { this[EnabledKeyName] = value; }
    }

    public string[] AllowedUsersArray {
        get {
            if (string.IsNullOrEmpty(AllowUsers))
                return null;

            return AllowUsers.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
        }
    }

    public string[] AllowRolesArray {
        get {
            if (string.IsNullOrEmpty(AllowRoles))
                return null;

            return AllowRoles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        }
    }
}

Example Web.config

<configuration>
    <configSections>
        <section name="accessControl" type="MyWebsite.Config.AccessControlSection, MyWebsite" />
    </configSections>

    <accessControl>
        <forceLockout enabled="true" defaultPage="~/inviteonly.htm" 
            logOnUrl="~/logon" 
            logOffUrl="~/logoff" 
            allowRoles="Members" />
    </accessControl>

</configuration>

With the above configuration, any user who is not logged in or not a member of the role 'Members' would be redirected to '~/inviteonly.htm'. You can specify multiple allowed roles and/or users by comma-separating the values in the 'allowRoles' and 'allowUsers' attributes.

The AccessControlAttribute must be registered as a global filter or alternatively placed on a BaseController class definition to get everything working.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文