【问题标题】:Asp.net MVC Authorize attribute, redirect to custom "no rights" pageAsp.net MVC Authorize 属性,重定向到自定义“无权限”页面
【发布时间】:2010-12-16 04:37:35
【问题描述】:

当经过身份验证的用户没有权限时,Asp.net MVC2 会重定向到带有response 302 的登录页面。

我想分成两个动作

  1. 如果用户未通过身份验证,则执行其操作,重定向到登录页面。
  2. 如果用户已通过身份验证但没有所需的权限,则返回相应的 http 状态代码并显示无权限的页面。

有什么办法吗?还是我在授权和表单身份验证方面做错了什么?我能想到的唯一方法是编写我想避免的自定义授权属性。

【问题讨论】:

  • 哈哈“无权老兄”页面...哈哈

标签: asp.net-mvc asp.net-mvc-2


【解决方案1】:

您可以像这样编写自定义过滤器属性:

public class CustomAuthorizeAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity == null || !filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                filterContext.Result = new RedirectResult(System.Web.Security.FormsAuthentication.LoginUrl + "?returnUrl=" +
                filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.RawUrl));
            }

            //Check user right here
            if (userNotRight)
            {
                filterContext.HttpContext.Response.StatusCode = 302;
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }
    }

并在控制器中使用它:

[CustomAuthorize]
public class HomeController : Controller
{

}

【讨论】:

  • 您应该使用 AuthorizeAttribute 而不是 ActionFilterAttribute 来进行授权。
  • @ReinierDG 那么,如何使用 AuthorizeAttribute 来实现呢?
  • 如果属性在类上并且有问题的操作具有AllowAnonymous,这似乎会失败
【解决方案2】:

您可以编写自定义授权属性,如果用户未通过身份验证,则在 AuthorizeCore 方法中返回 HttpUnauthorizedResult,并且如果他已通过身份验证但未在角色中执行您想要的其他操作。请注意,如果您返回 401 状态代码,FormsAuthentication 框架最终将使用 302 重定向到登录页面。

【讨论】:

  • 但是...您只能从 AuthorizeCore 返回一个布尔值。您必须覆盖 OnAuthorization 以返回 ActionResult
  • @EduardoMolteni,您可以重写 HandleUnauthorizedRequest 方法以返回您想要的结果。
【解决方案3】:

正如Customizing authorization in ASP.NET MVC 中所建议的那样,您可以将 AuthorizeAttribute 子类化以拦截经过身份验证但未经授权的场景并将结果替换为重定向。

【讨论】:

  • 这样更好,尤其是对缓存结果进行授权。
【解决方案4】:

实现自定义AuthorizeAttribute 并添加以下覆盖。基础是检查用户是否经过身份验证但未授权,然后重定向到您自己的“拒绝访问”页面。希望这会有所帮助!

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

    // Check if user is authenticated and if this action requires authorization
    if (filterContext.HttpContext.User.Identity.IsAuthenticated
        && filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true)
        || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true))
    {
        List<object> attributes = new List<object>(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));
        attributes.AddRange(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));

        // Check all authorzation attributes
        foreach (var attribute in attributes)
        {
            var authAttribute = attribute as AuthorizeAttribute;
            if (authAttribute != null)
            {
                if (!filterContext.HttpContext.User.IsInRole(authAttribute.Roles))
                {
                    // User is not authorized so redirect to our access denied error page
                    filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary 
                            {
                                { "area", "" },
                                { "controller", "Error" },
                                { "action", "AccessDenied" }
                            });
                    break;
                }
            }
        }
    }
}

【讨论】:

  • 添加这个 .... if (authAttribute != null && !string.IsNullOrEmpty(authAttribute.Roles))
【解决方案5】:

类似于@hellangle 和@Andreas 提出的解决方案,我使用以下代码解决了这个问题:

public class CustomizedAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var userAuthInfo = GetUserAuthInfo();

        if (!userAuthInfo.IsAuthenticated())
        {
            filterContext.Result = new RedirectResult(UrlToYourLoginPage);
            return;
        }

        if (!userAuthInfo.IsAuthorized())
        {
            var result = new ViewResult {ViewName = "UnAuthorized"};
            result.ViewBag.Message = "Sorry! You are not authorized to do this!";
            filterContext.Result = result;
        }
    }
}

当然,你需要根据你的具体需求实现用户授权信息类和相关方法(GetUserAuthInfo、IsAuthenticated、IsAuthorized)。一个名为“UnAuthorized”的视图也应该放在 MVC 引擎可以找到的地方。然后它可以用于控制器类(在@hellangle 的回答中指出)或操作方法:

[CustomizedAuthorizeAttribute]
public class TargetController : Controller
{
    [CustomizedAuthorizeAttribute]
    public ActionResult TargetAction()
    {
        // Your Code
    }

}

为了给各种控制器类和动作方法提供不同的访问控制策略,为CustomizedAuthorizeAttribute类实现一个构造函数,它接受代表访问控制信息的参数,然后相应地实例化CustomizedAuthorizeAttribute类。

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 2021-12-31
    • 1970-01-01
    • 2020-07-19
    • 2012-10-28
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2012-10-27
    相关资源
    最近更新 更多