我知道可以使用Authorize属性来装饰控制器来控制访问,我不知道的是在区域中的所有控制器/视图中强制实施安全性的可接受或正确方法.
在web.config,区域注册或其他一些地方有什么东西可以应用授权安全性吗?
我试图找到一个实现自定义的解决方案,System.Web.Mvc.AuthorizeAttribute通过从它派生并覆盖它的一些方法.
我正在尝试的每种方法,我都面临着MVC 5的默认授权机制中的某些问题,这些问题阻止我正确扩展它.
我已经在SO和许多专用资源上完成了关于这个领域的大量研究,但是我无法像现在那样得到一个可靠的解决方案.
第一个限制:
我的授权逻辑需要额外的数据,如控制器和方法名称以及应用于它们的属性,而不是数据的有限部分HttpContextBase能够提供.
例:
public override void OnAuthorization(AuthorizationContext filterContext)
{
...
var actionDescriptor = filterContext.ActionDescriptor;
var currentAction = actionDescriptor.ActionName;
var currentController = actionDescriptor.ControllerDescriptor.ControllerName;
var hasHttpPostAttribute = actionDescriptor.GetCustomAttributes(typeof(HttpPostAttribute), true).Any();
var hasHttpGetAttribute = actionDescriptor.GetCustomAttributes(typeof(HttpGetAttribute), true).Any();
var isAuthorized = securitySettingsProvider.IsAuthorized(
currenPrincipal, currentAction, currentController, hasHttpPostAttribute, hasHttpGetAttribute);
...
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么我无法在AuthorizeCore()方法覆盖中实现我的授权逻辑,因为它只HttpContextBase作为参数和我需要做出授权决策AuthorizationContext.
这导致我将我的授权逻辑放到OnAuthorization()方法覆盖中,如上例所示.
但是在这里我们遇到了第二个限制:缓存系统调用
该AuthorizeCore()方法来做出授权决策,是否应当使用缓存ActionResult或相应的控制器方法来提供当前请求,以创建新的ActionResult.
所以我们不能忘记AuthorizeCore()并且OnAuthorization()只使用它. …
我正在编写一个ASP.NET MVC 3应用程序,我有很多角色:
系统管理员,客户管理员,预算所有者,应用所有者
我知道我可以使用[Authorize(Roles ="...")]属性轻松限制对某些控制器(和操作方法)的访问.
但是,某些授权不仅仅基于角色,而是基于权限.例如,预算所有者应该只能访问分配给其成本中心的预算 - 而不是其他人的预算.
目前我在action方法中有一些代码来检查:
if(UserCapabilities.CanAccessBudget(budgetId))
{
// get budget and show view
}
else
{
// redirect to index action
}
Run Code Online (Sandbox Code Playgroud)
这开始使我的代码变得混乱并使检查安全性变成一场噩梦 - 因为我有许多需要这些不同类型的授权检查的动作方法.
我有一个想法是编写一些自定义属性,我可以用它来装饰我的操作方法并清理我的代码:
//
// GET: /Budgets/View/1
[CanAccessBudget]
public ActionResult View(int id)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
人们怎么想?编写自定义属性是最干净,最易维护的方法吗?
我理解重写一个方法/函数从它在基类中的实现重新定义它在派生类中的实现.
现在令我困惑的是,如果我覆盖ASP.NET中的一个类CreateChildControls()(我没有特殊原因随机选择它),VS2008自动生成:
protected override void CreateChildControls()
{
base.CreateChildControls();
}
Run Code Online (Sandbox Code Playgroud)
足够好,默认实现只调用基类' CreateChildControls().
所以,如果我想运行一些代码,因为我不知道如何base.CreateChildControls(),我应该这样做:
protected override void CreateChildControls()
{
/*My Code Here*/
base.CreateChildControls();
}
Run Code Online (Sandbox Code Playgroud)
或者,base.CreateChildControls()完全忽略了什么,只是做了
protected override void CreateChildControls()
{
/*My Code Here*/
}
Run Code Online (Sandbox Code Playgroud) 我有一个由[Project]控制器使用的类.控制器和不同区域的控制器.我怎样才能确定控制器的位置?(我想我可以查看HttpContext.Current.Request的属性 - 但我正在寻找一种"正确的"MVC方式).谢谢.
那是:
[Project].Helpers // called by:
[Project].Controllers
[Project].Areas.[Area].Controllers
// how could I determine the caller from [Project].Helpers?
Run Code Online (Sandbox Code Playgroud) 它是一个asp.net核心webapi项目,我只是把[Authorize]属性放在了保护那些apis上。如果用户未授权,api 将返回“401 未授权”。
我的问题是如果未经授权,我如何本地化“401 未授权”消息。
对于其他数据注释,我可以设置DataAnnotation 属性的ErrorMessage属性,例如 [Required(ErrorMessage = "xxx")]。但是,AuthorizeAttribute 没有这样的属性。
感谢@Athanasios,我想出了我的解决方案,希望它可以帮助某人。(ErrorMessages 只是一个共享类)。
using System;
using System.Threading.Tasks;
using YourNamespace.Messages;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
namespace YourNamespace.Attributes
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class LocalizedAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public string UnauthorizedErrorMessage { get; set; }
public string ForbiddenErrorMessage { get; set; }
public LocalizedAuthorizeAttribute()
{
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{ …Run Code Online (Sandbox Code Playgroud)