1

我正在使用 VS 2011 开发一个 asp.net MVC 4 应用程序。我有一个带有自定义 AuthorizeAttribute 的自定义角色提供程序来确定用户的角色,如果他们不是特定角色的成员,他们将重定向到拒绝访问页面. 到目前为止,当我使用自定义属性装饰任何控制器操作时,我所做的工作,但是当我将属性添加到控制器时,它会在 IE 和 FF 中出现不同的错误。我的自定义属性:

public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
    public string RedirectActionName { get; set; }
    public string RedirectControllerName { get; set; }
    private IAccountRepository _accountRepository;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var user = httpContext.User;
        this._accountRepository = new AccountRepository();
        var accessAllowed = false;    
        var allowedRoles = this.Roles.Split(',');

        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        // Get roles for current user
        var roles = this._accountRepository.GetRoles(user.Identity.Name);

        foreach (var allowedRole in allowedRoles)
        {
            if (roles.Contains(allowedRole))
            {
                accessAllowed = true;
            }
        }

        if (!accessAllowed)
        {
            return false;
        }

        return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.Result is HttpUnauthorizedResult)
        {   
            var values = new RouteValueDictionary(new
            {
                action = this.RedirectActionName == "" ? "AccessDenied" : this.RedirectActionName,
                controller = this.RedirectControllerName == "" ? "Home" : this.RedirectControllerName
            });

            filterContext.Result = new RedirectToRouteResult(values);
        }
    }
}

我还在 RegisterGlobalFilters 中添加了一个全局属性(我尝试删除它但仍然遇到相同的问题):

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new System.Web.Mvc.AuthorizeAttribute());
}

当我用属性装饰一个动作时,它可以正常工作:

[AccessDeniedAuthorize(RedirectActionName = "AccessDenied", RedirectControllerName = "Home", Roles = "propdat")]
public ActionResult Index()
{
    this.ViewBag.Message = "Welcome.";

    return this.View();
}

但是当我将它添加到控制器时,它会完全中断:

[AccessDeniedAuthorize(RedirectActionName = "AccessDenied", RedirectControllerName = "Home", Roles = "propdat")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        this.ViewBag.Message = "Welcome.";

        return this.View();
    }

    public ActionResult AccessDenied()
    {
        this.ViewBag.Message = "You are not authorised to view this page. Please contact your administrator.";

        return this.View();            
    }
}

这些角色是通过一个看起来不错的存储库从我的数据库返回的。在 IE 中,我得到标准的“Internet Explorer 无法显示网页”错误,而在 Firefox 中出现了一个非常奇怪的错误:

页面未正确重定向
Firefox 检测到服务器正在以永远不会完成的方式重定向对该地址的请求。

  • 此问题有时可能是由禁用或拒绝接受 cookie 引起的。

在 IE 中,url 保留在 Home url:

http://localhost:1989

但 FF 在 url 更改为我在属性中指定的视图时执行重定向:

http://localhost:1989/Home/AccessDenied
4

2 回答 2

2

再看看你的代码,伙计:)

你正在HomeController用你的装饰,AccessDeniedAuthorizeAttribute但你HomeController包含你AccessDenied无法拒绝的行为。

所以问题是,每当AccessDeniedAuthorizeAttribute尝试将当前用户重定向到AccessDeniedActionaccessAllowed时,这将是错误的,这会将您加载到循环循环中。

解决方案是:

要么把你的AccessDenied动作放在另一个“HelperController”中,不要用你的属性装饰这个 HelperController。

或者只是将此属性添加到除了操作HomeController之外的所有操作AccessDenied

于 2012-06-04T10:21:42.700 回答
1

我认为你需要做的是:

  1. 删除全局过滤器 - 这将锁定每个 MVC 控制器(不是 WebAPI)上的每个操作 - 强制如果用户未经过身份验证或未授权,则框架将返回重定向到“登录 url”设置(在 authentication > forms 元素中找到 - 假设您使用的是 Forms 身份验证) - 请注意,全局过滤器不会在您的自定义属性中使用重定向 url。

  2. 将您的自定义属性放在主控制器上,然后将 [AllowAnnoymous] 属性添加到 AccessDenied 操作,最重要的是,将此代码添加到您的自定义属性(这是确保它跳过具有 [AllowAnnoymous] 属性的操作所必需的):

        bool skipAuthorization = 
        filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true) 
        || 
        filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
    
        if (skipAuthorization)
        {
            return;
        }
    

顺便说一句,Firefox 告诉你的是你得到了一个无限的重定向循环......因为初始请求未经授权,框架重定向到登录 url,但是该请求被授权检查捕获并且本身被重定向......所以依此类推,直到浏览器放弃并停止循环。

于 2014-04-21T11:19:15.730 回答