asp.net-mvc 将 MVC 中未经授权的页面访问重定向到自定义视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22074474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect Unauthorized Page Access in MVC to Custom View
提问by user2739418
I have an MVC website in which access is based on various Roles. Once a user logs into the system they can see navigation to the pages for which they are authorized. However, some users may still try to access pages using a direct URL. If they do, the system automatically redirects them to the Login Page. Instead of the Login Page I want to redirect them to another view (Unauthorized).
我有一个 MVC 网站,其中访问基于各种角色。用户登录系统后,他们可以看到导航到他们授权的页面。但是,某些用户可能仍会尝试使用直接 URL 访问页面。如果他们这样做,系统会自动将他们重定向到登录页面。我想将它们重定向到另一个视图(未经授权),而不是登录页面。
Web.Config has the following entry:
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>
I have registered these routes in Global.asax.cs as well.
我也在 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 }
);
Will it be enough?
就够了吗?
采纳答案by user2739418
With following change it is working
通过以下更改,它正在工作
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);
}
}
}
And then applying on Controller or Action as below:
然后在 Controller 或 Action 上应用如下:
[CustomAuthorize(Roles = "Admin")]
With above approach I need to revisit all the controller/actions and change the Authorized attribute! Also some testing will be needed.
使用上述方法,我需要重新访问所有控制器/操作并更改 Authorized 属性!还需要一些测试。
I am still not sure why Web.Config route not working as same has been explained in MVC Documentation. May be something has changed in MVC 4!
我仍然不确定为什么 Web.Config 路由不能像 MVC 文档中解释的那样工作。MVC 4 中可能发生了一些变化!
回答by The Vojtisek
After some research I think the easiest answer to this problem is just creating custom authorize, very similar to the one by jbbi (but that one didn't work since the "new HttpUnauthorizedResult()" is internaly automatically redirecting to the login - at least in mvc 5 with identity)
经过一些研究,我认为这个问题最简单的答案就是创建自定义授权,与 jbbi 的非常相似(但那个没有工作,因为“新的 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" }));
}
}
}
and the usage is the same as the default Authorize:
用法与默认 Authorize 相同:
[CustomAuthorize(Roles = "Administrator")]
Then, just to do things right, don't forget to send out the Http code of the error page. e.g like this in the controller.
然后,为了做正确的事情,不要忘记将错误页面的Http代码发送出去。例如像这样在控制器中。
public ActionResult AccessDenied()
{
Response.StatusCode = 403;
return View();
}
It's easy, it works and even I (a .net mvc rookie) understand this.
这很简单,很有效,甚至我(一个 .net mvc 新手)也明白这一点。
Note:It doesn't work the same with a 401 code - it will always take over the 401 and internaly redirect it to the login. But in my case is, by definition, the 403 also fitting.
注意:它与 401 代码的工作方式不同 - 它总是会接管 401 并在内部将其重定向到登录名。但就我而言,根据定义,403 也很合适。
回答by eiximenis
Probably best way to handle this is to create an additional action filter, that redirects the user to the specified error page if he does not belong to the specified role. So, this methods will have both filters applied: [Authorize] (with no roles) to protect from unauthenticated users and redirecting them to the Login Page. And your custom Attribute with the roles. Code SIMILAR to this (not tested):
可能最好的处理方法是创建一个额外的操作过滤器,如果用户不属于指定的角色,则将用户重定向到指定的错误页面。因此,此方法将应用两个过滤器:[授权](无角色)以防止未经身份验证的用户并将其重定向到登录页面。以及带有角色的自定义属性。与此类似的代码(未测试):
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");
}
}
}
Apply both [Authorize] and [RoleFilter] to the actions...
将 [Authorize] 和 [RoleFilter] 应用于操作...
Hope this helps!
希望这可以帮助!
回答by binard
I think you should create your own Authorize filter attribute which inherit of the default Authorize filter
我认为您应该创建自己的 Authorize 过滤器属性,该属性继承默认的 Authorize 过滤器
public class CustomAuthorize: AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure
}
}

