Asp.net mvc 2 ASP.NET MVC 2授权问题

Asp.net mvc 2 ASP.NET MVC 2授权问题,asp.net-mvc-2,forms-authentication,Asp.net Mvc 2,Forms Authentication,我正在使用自定义会员资格提供商。一切都很顺利。但是,在我的web.config文件中,我启用了“拒绝用户”,因此整个网站都被锁定 这很有效。用户将被重定向到登录页面 现在,我有几个控制器/操作,我想允许匿名访问。关于页面、密码重置等 我唯一能弄清楚如何做到这一点的方法是解锁整个站点,在每个控制器上放置[Authorize]属性,并为我想要匿名的控制器/操作删除它们 对我来说,这似乎是倒退。我更喜欢在默认情况下锁定所有内容并解锁匿名内容 有办法解决这个问题吗 谢谢 我可以想出其他方法来实现这一点,

我正在使用自定义会员资格提供商。一切都很顺利。但是,在我的web.config文件中,我启用了“拒绝用户”,因此整个网站都被锁定

这很有效。用户将被重定向到登录页面

现在,我有几个控制器/操作,我想允许匿名访问。关于页面、密码重置等

我唯一能弄清楚如何做到这一点的方法是解锁整个站点,在每个控制器上放置[Authorize]属性,并为我想要匿名的控制器/操作删除它们

对我来说,这似乎是倒退。我更喜欢在默认情况下锁定所有内容并解锁匿名内容

有办法解决这个问题吗


谢谢

我可以想出其他方法来实现这一点,但它们都涉及使用自定义属性。实现这一点的一种方法是让一个基本控制器使用所有控制器派生的自定义属性。该属性将被定制,以防止匿名(和未经授权)访问某个操作,除非该操作的控制器或该操作本身已被另一个属性修饰——比如AnonymousEnabledAttribute。您的所有控制器都将从此控制器派生,从而继承其标准的“默认情况下不匿名”行为。然后,您只需使用AnonymousEnabledAttribute来装饰您想要匿名的控制器/操作——为该控制器或操作提供覆盖。或者,对于控制器,只需不从受保护的控制器继承,它的所有操作都将公开

哦,你的整个网站必须保持开放

[OverridableAuthorize]
public abstract class ProtectedController : Controller
{
}

public class MostlyProtectedController : ProtectedController
{
    public ActionResult ProtectedAction()
    {
    }

    [AnonymousEnabled]
    public ActionResult PublicAction()
    {
    }
}

[AnonymousEnabled]
public class ExplicitlyPublicController : ProtectedController
{
    // inherits additional behaviors, but anonymous is enabled by attribute
}

public class PublicByOmissionController : Controller
{
    // doesn't inherit and is thus public -- assuming whole site is open
}

public class AnonymousEnabledAttribute : Attribute
{
}

public class OverridableAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext context )
    {
          context.HttpContext.Items["ActionDescriptor"] = context.ActionDescriptor;
          base.OnAuthorize( context );
    }

    public override bool AuthorizeCore( HttpContextBase context )
    {
         var actionDescriptor = context.Items["ActionDescriptor"] as ActionDescriptor;
         if (actionDescriptor == null)
         {
             throw InvalidOperationException( "ActionDescriptor missing from context" );
         }
         var attribute = actionDescriptor
                             .GetCustomAttributes( typeof(AnonymousEnabledAttribute,true)
                             .FirstOrDefault();
         if (attribute == null)
         {
             return base.AuthorizeCore( context );
         }
         return true;
    }
}

您可以在web.config文件中为希望始终允许的控制器创建一个位置:

<configuration>
    <system.web>
        ...
        <authorization>
            <deny users="?" />
        </authorization>
    </system.web>
    ...
    <location path="MyArea/MyController">
        <system.web>
            <authorization>
                <allow users="*" />
            </authorization>
        </system.web>
    </location>
    ...
</configuration>

...
...
...

谢谢您的建议。因此,这意味着站点(根据web.config)将完全打开,但默认情况下所有控制器都将被锁定,只要它们继承自ProtectedController?@cbmeeks-正确。此外,我认为使用AuthorizeAttribute(或从它派生的东西),即MVC安全性,肯定比尝试混合使用基于WebForms的安全性和MVC安全性更可取。**注意**AuthorizeAttribute类在创建后必须是不可变的。您可以使用HttpContext.Items来存储ActionDescriptor,但绝对不能将其存储为类内的实例字段。这样做的原因是AuthorizeAttribute的单个实例可以用于处理多个并发请求,通过引入实例字段,您的安全代码中现在有了竞争条件。谢谢,但这似乎从来都不起作用。我已经把它放进去了,但它仍然需要匿名行动的授权。@cbmeeks:我不知道该说什么。我们使用的是这种方法,对我们来说效果很好。**注意**尝试将基于MVC的安全性与MVC安全性相混合和匹配会导致灾难-基于文件的安全性适用于基于文件的资源,如.aspx页面。因为控制器类是基于类型而不是基于文件的,所以可以绕过基于-的安全性。@Levi:你能详细说明一下吗?由于我只是列出了某些控制器的已知位置,这难道不应该阻止未登录的用户访问任何其他控制器吗?如何绕过这一点?通常,要审核应用程序中的每一条路由以查看它们最终可以激活哪些控制器是极其困难的(几乎不可能的)。很有可能有另一条路径不在MyArea区域内,但与路径MyArea/MyController/Foo匹配,并且该路径可用于攻击任意控制器。在这种情况下,您的标签将允许访问。即使您现在没有这样的路由,将来添加到路由表中也有可能触发它。