在ASP.NET MVC中重写授权属性
我有一个MVC控制器基类,在这个基类上我应用了Authorize属性,因为我希望几乎所有的控制器(及其操作)都得到授权 但是,我需要有一个控制器和另一个未经授权的控制器的行动。我希望能够用在ASP.NET MVC中重写授权属性,.net,asp.net-mvc,security,authentication,authorize,.net,Asp.net Mvc,Security,Authentication,Authorize,我有一个MVC控制器基类,在这个基类上我应用了Authorize属性,因为我希望几乎所有的控制器(及其操作)都得到授权 但是,我需要有一个控制器和另一个未经授权的控制器的行动。我希望能够用[Authorize(false)]或其他东西装饰它们,但这不可用 有什么想法吗?编辑:由于ASP.NET MVC 4,最好的方法就是简单地使用内置属性 下面的答案是指ASP.NET MVC的早期版本 您可以创建一个自定义授权属性,该属性继承自标准AuthorizeAttribute,并带有可选的bool参数,
[Authorize(false)]
或其他东西装饰它们,但这不可用
有什么想法吗?编辑:由于ASP.NET MVC 4,最好的方法就是简单地使用内置属性 下面的答案是指ASP.NET MVC的早期版本 您可以创建一个自定义授权属性,该属性继承自标准AuthorizeAttribute,并带有可选的bool参数,以指定是否需要授权
public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
private readonly bool _authorize;
public OptionalAuthorizeAttribute()
{
_authorize = true;
}
public OptionalAuthorizeAttribute(bool authorize)
{
_authorize = authorize;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if(!_authorize)
return true;
return base.AuthorizeCore(httpContext);
}
}
然后可以使用该属性装饰基本控制器:
[OptionalAuthorize]
public class ControllerBase : Controller
{
}
对于任何不需要授权的控制器,只需使用带有“false”的覆盖,例如
[OptionalAuthorize(false)]
public class TestController : ControllerBase
{
public ActionResult Index()
{
return View();
}
}
我个人的看法是将控制器拆分。只需为不需要身份验证的操作创建另一个控制器 或者你可以:
BaseController
不需要身份验证-这里有您所有的“基本资料”:BaseAuthController:BaseController
此处的所有操作都需要身份验证
这样,您可以在需要时进行身份验证,只需从特定类派生即可。如果您只希望一个操作在其他授权的控制器上未经授权,则可以执行以下操作:
public class RequiresAuthorizationAttribute : ActionFilterAttribute
{
private readonly bool _authorize;
public RequiresAuthorizationAttribute()
{
_authorize = true;
}
public RequiresAuthorizationAttribute(bool authorize)
{
_authorize = authorize;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var overridingAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequiresAuthorizationAttribute), false);
if (overridingAttributes.Length > 0 && overridingAttributes[0] as RequiresAuthorizationAttribute != null && !((RequiresAuthorizationAttribute)overridingAttributes[0])._authorize)
return;
if (_authorize)
{
//redirect if not authenticated
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
//use the current url for the redirect
var redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;
//send them off to the login page
//var redirectUrl = string.Format("?RedirectUrl={0}", redirectOnSuccess);
var loginUrl = LinkBuilder.BuildUrlFromExpression<HomeController>(filterContext.RequestContext, RouteTable.Routes,
x => x.Login(redirectOnSuccess));
filterContext.HttpContext.Response.Redirect(loginUrl, true);
}
}
}
}
public类RequiresAuthorizationAttribute:ActionFilterAttribute
{
私有只读bool\u授权;
public RequiresAuthorizationAttribute()
{
_授权=真;
}
public RequiresAuthorizationAttribute(bool授权)
{
_授权=授权;
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
var overridingAttributes=filterContext.ActionDescriptor.GetCustomAttributes(typeof(requireAuthorizationAttribute),false);
如果(overridingAttributes.Length>0&&overridingAttributes[0]作为requireAuthorizationAttribute!=null&!((requireAuthorizationAttribute)overridingAttributes[0])。\u authorize
返回;
如果(授权)
{
//如果未通过身份验证,则重定向
如果(!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
//使用重定向的当前url
var redirectOnSuccess=filterContext.HttpContext.Request.Url.AbsolutePath;
//将它们发送到登录页面
//var redirectUrl=string.Format(“?redirectUrl={0}”,redirectOnSuccess);
var loginUrl=LinkBuilder.BuildUrlFromExpression(filterContext.RequestContext,RouteTable.Routes,
x=>x.Login(重定向成功));
filterContext.HttpContext.Response.Redirect(loginUrl,true);
}
}
}
}
ASP.NET MVC 4似乎通过添加属性“修复”了这一问题
:
我已经想到了这一点,但我希望有一个更简单的解决办法。但是,如果“他们”没有提供,那么您的解决方案是最好的。最好使用
[AllowAnonymous]
属性。等等。。。那么控制器只尊重某个特定类型的顶级类的属性?你知道为什么使用AllowAnonymous会更好吗?因为你有更好的控制力。在我的例子中,我希望仅对某些环境禁用授权端点,例如,localhost不需要它。这提供了一个比我在startup.cs中要做的更优雅的解决方案。11年后我们在这里讨论。
[Authorize]
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult Login()
{
// ...
}
// ...
}