Asp.net MVC 授权属性,重定向到自定义“无权限”属性页

发布于 2024-10-08 12:28:24 字数 247 浏览 0 评论 0原文

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

我想分为两个操作

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

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

Asp.net MVC2 does redirect to login page with response 302 when authenticated user has no rights.

I would like to split into two actions

  1. If user is not authenticated then do what it does, redirect to login page.
  2. If user is authenticated but has no required rights then return appropriate http status code and show no rights dude page.

Is there any way to do it? Or am I doing something wrong with authorize and form authentication? Only way I can think of is by writing custom authorize attribute, which I want to avoid.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

粉红×色少女 2024-10-15 12:28:24

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

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
{

}

You could write custom filter attribute like this:

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();
            }
        }
    }

And use it in controller:

[CustomAuthorize]
public class HomeController : Controller
{

}
游魂 2024-10-15 12:28:24

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

You could write a custom authorize attribute and in the AuthorizeCore method if the user is not authenticated return a HttpUnauthorizedResult and if he is authenticated but not in roles perform some other action you would like. Note that if you return 401 status code the FormsAuthentication framework will eventually redirect with 302 to the login page.

山色无中 2024-10-15 12:28:24

正如在 ASP.NET MVC 中自定义授权中所建议的,您可以子类化 AuthorizeAttribute 以拦截经过身份验证但未经授权的场景,并用重定向替换结果。

As suggested in Customizing authorization in ASP.NET MVC, you could subclass the AuthorizeAttribute to intercept the authenticated-but-unauthorized scenario and replace the result with a redirect.

狠疯拽 2024-10-15 12:28:24

实现自定义 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;
                }
            }
        }
    }
}

Implement a custom AuthorizeAttribute and add the following override. The basics is to check if user is authenticated but not authorized and then redirect to you own "Access Denied" page. Hope this helps!

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;
                }
            }
        }
    }
}
葬花如无物 2024-10-15 12:28:24

与@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类。

Similar to solutions suggested by @hellangle and @Andreas, I used the following code to solve this problem:

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;
        }
    }
}

Of course, you need to implement the user authorization information class and related methods (GetUserAuthInfo, IsAuthenticated, IsAuthorized) according to your specific needs. Also a View named 'UnAuthorized' should be put to somewhere the MVC engine can find. Then it can be used on a controller class (pointed out in @hellangle's answer) or a action method:

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

}

In order to provide different access control strategy for various controller classes and action methods, implements a constructor for CustomizedAuthorizeAttribute class which accepts parameter(s) representing access control information and then Instantiate CustomizedAuthorizeAttribute class accordingly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文