将MVC中未经授权的页面访问重定向到自定义视图。

23

我有一个MVC网站,其中的访问权限是基于不同的角色控制的。一旦用户登录系统,他们可以看到导航到他们被授权的页面。然而,有些用户可能仍然尝试使用直接的URL访问某些页面。如果他们这样做,系统将自动重定向到登录页面。我希望将其重定向到另一个视图(未经授权)而不是登录页面。

Web.Config 文件中有以下条目:

    <customErrors mode="On">
      <error statusCode="401" redirect="~/Home/Unauthorized" />
      <error statusCode="404" redirect="~/Home/PageNotFound" />
    </customErrors>
    <authentication mode="Forms">
<forms name="Development" loginUrl="~/Account/Login" cookieless="UseCookies" timeout="120"></forms>
    </authentication>

我已经在Global.asax.cs中注册了这些路由。

routes.MapRoute(
    name: "Unauthorized",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Unauthorized", id = UrlParameter.Optional }
   );


routes.MapRoute(
    name: "PageNotFound",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "PageNotFound", id = UrlParameter.Optional }
    );

够用吗?

5个回答

36
经过一番研究,我认为最简单的解决方法就是创建自定义授权,与jbbi的授权非常相似(但由于“new HttpUnauthorizedResult()”在MVC 5和身份验证中会自动重定向到登录页面(至少如此)),所以那个授权并没有起作用。
public class CustomAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            //if not logged, it will work as normal Authorize and redirect to the Login
            base.HandleUnauthorizedRequest(filterContext);

        }
        else
        {
            //logged and wihout the role to access it - redirect to the custom controller action
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));
        }
    }
}

用法与默认的 Authorize 相同:

[CustomAuthorize(Roles = "Administrator")]

然后,为了做到正确,别忘记在控制器中发送出错误页面的 Http 状态码。例如:

public ActionResult AccessDenied()
{
    Response.StatusCode = 403;
    return View();
}

这很简单,而且有效,就算是我这样一个 .net mvc 菜鸟也能明白。

注意:对于 401 状态码,它的处理方式不同 - 它会始终将请求重定向到登录页面。但在我的情况下,403 代码也适用。


我忘记了那时候我是怎么做的。上面看起来不错。我会尝试实现它并查看是否按预期工作。 - user2739418
2
请确保使用System.Web.Mvc命名空间,而不是System.Web.Http。它们都有HandleUnauthorizedRequest方法。 - Ali Kashanchi

22

使用以下更改后它可以正常工作

public class CustomAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure
          filterContext.Result = new RedirectResult("~/Home/Unauthorized");
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (this.AuthorizeCore(filterContext.HttpContext))
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            this.HandleUnauthorizedRequest(filterContext);
        }
    }

}

然后在控制器或操作上应用如下:

[CustomAuthorize(Roles = "Admin")]

通过以上方法,我需要重新访问所有的控制器/操作并更改Authorized标记!同时需要进行一些测试。

我仍然不确定为什么Web.Config路由不能像MVC文档中所解释的那样工作。可能是在MVC 4中有一些变化!


4

处理这个问题的最佳方法可能是创建一个额外的操作过滤器,如果用户不属于指定的角色,则将其重定向到指定的错误页面。 因此,这些方法将应用两个过滤器:[Authorize](没有角色)来保护未经身份验证的用户,并将它们重定向到登录页面。和您自定义的带有角色的属性。代码类似于以下内容(未经测试):

public class RoleFilterAttribute : ActionFilterAttribute
{
    public string Role { get; set; }
    public override void OnActionExecuting(ActionExecutingContext ctx)
    {
        // Assume that we have user identity because Authorize is also
        // applied
        var user = ctx.HttpContext.User;
        if (!user.IsInRole(Role))
        {
            ctx.Result = new RedirectResult("url_needed_here");
        }
    }
}

将[Authorize]和[RoleFilter]都应用于操作...

希望这有所帮助!


"public string Role { get; set; }" 这个属性如何知道用户属于哪个角色?尝试一下吧! - user2739418
你好,这个属性是用来存储你想要检查的角色。因此,如果你想要仅为“经理”保护一个方法,你可以在你的操作中使用:[RoleFilter(Role="Manager")]。 这个例子只检查一个角色,但将其扩展到检查N个角色(即用逗号分隔)是微不足道的。真正执行检查的方法是IsInRole。 - eiximenis

2
我认为您应该创建自己的授权过滤器属性,继承默认的授权过滤器。
public class CustomAuthorize: AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
       filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure
    }
}

1
由于其他方法无效,我选择这条路线。谢谢!我仍然会尝试找出为什么 web.config 没有起作用。如果有任何发现,我会在这里发布!干杯! - user2739418

0

将未经授权的页面访问重定向到自定义视图-Asp.net C#

  1. 在login.aspx.cs中的页面加载事件中添加以下代码:
     protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                
                txtUsername.Focus();
                if (!IsPostBack)
                {
                    if (Request.IsAuthenticated && !string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
                    {
                        Response.Redirect("UnauthorizedAccess.aspx", false);
                        return;
                    }                   
                    Session.Clear();
                    Session.Abandon();

                }                
            }
            catch (Exception ex)
            {
                this.errLogin.Text = ex.Message;                
            }
        }

2) 创建 UnauthorizedAccess.aspx

    <h1>Unauthorized</h1>

        
            <p>Sorry, you are not authorized to access this page</p>
        
           <asp:LinkButton ID="lnkhome" runat="server" CssClass="btn btn-success1" OnClick="lnkhome_Click"
               CausesValidation="false"><span class="fa fa-home"/> Back to Home</asp:LinkButton>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接